码迷,mamicode.com
首页 > 其他好文 > 详细

[2017浙工大之江学院决赛 E] qwb和李主席(折半枚举,二分)

时间:2017-06-03 13:53:47      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:pre   2.0   ems   ret   sort   for   div   部分   min   

题目链接:http://115.231.222.240:8081/JudgeOnline/problem.php?cid=1005&pid=4

题意:把一个数组拆成两部分,使得两个集合分别的和的差的绝对值最小。

做过类似的,用01背包,求sum/2容量下的最大价值,这样可以拆成两个集合,并且符合题意。

但是这题浮点数,而且物品价值1e9,不能背包了。

n<=36,也不能直接枚举。

可以把n个数拆成两部分,先枚举一部分的组合情况,把和求出来,再枚举另一部分,枚举到一个和x后在第一部分的和里二分地枚举一个和y,使得x+y最接近sum/2。然后每次更新两部分的和A=x+y, B=sum-A,更新ret=min(abs(A-B))即可。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 66;
 5 int n, na, nb;
 6 double v[maxn], a[maxn], b[maxn];
 7 double s[1<<20], sum;
 8 
 9 double gao(double val) {
10     int lo = 1, hi = (1 << nb), ret = -1;
11     while(lo <= hi) {
12         int mid = (lo + hi) >> 1;
13         if((s[mid] + val) * 2.0 >= sum) {
14             ret = mid;
15             hi = mid - 1;
16         }
17         else lo = mid + 1;
18     }
19     double A = s[ret] + val , B = sum - A;
20     return abs(A - B);
21 }
22 
23 int main() {
24     // freopen("in", "r", stdin);
25     while(~scanf("%d",&n)) {
26         na = nb = 0;
27         sum = .0;
28         memset(s, 0, sizeof(s));
29         for(int i = 1; i <= n; i++) {
30             scanf("%lf", &v[i]);
31             sum += v[i];
32             if(i <= n / 2) a[na++] = v[i];
33             else b[nb++] = v[i];
34         }
35         for(int i = 0; i < (1 << na); i++) {
36             for(int j = 0; j < na; j++) {
37                 if(i & (1 << j)) s[i+1] += a[j];
38             }
39         }
40         sort(s+1, s+(1<<na)+1);
41         double ret = 1e18;
42         for(int i = 0; i < (1 << nb); i++) {
43             double tmp = .0;
44             for(int j = 0; j < nb; j++) {
45                 if(i & (1 << j)) tmp += b[j];
46             }
47             // double A = tmp + *lower_bound(s+1, s+(1<<na)+1, sum/2.0-tmp);
48             // double B = sum - A;
49             ret = min(ret, gao(tmp));
50         }
51         printf("%.2f\n", ret);
52     }
53     return 0;
54 }

 

[2017浙工大之江学院决赛 E] qwb和李主席(折半枚举,二分)

标签:pre   2.0   ems   ret   sort   for   div   部分   min   

原文地址:http://www.cnblogs.com/kirai/p/6936947.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!