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


    题目链接: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
    ", ret);
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    第一次面试准备
    第一次面试复盘(谐云)
    段子第二弹(乐趣就是把一件丢人的事儿不点破,让观众自己打开包袱,但是又不能太难理解,最好1秒半能反应过来)
    mac上安装配置allure(必定成功)
    Django和Python的版本对应关系
    http请求默认值
    mac安装brew
    一种解决方法 Error: No such file or directory @ rb_sysopen
    git提交代码的正确步骤
    C#DirectoryHelper文件夹IO
  • 原文地址:https://www.cnblogs.com/kirai/p/6936947.html
Copyright © 2020-2023  润新知