• TZOJ 1503 Incredible Cows(折半搜索+二分)


    描述

    Farmer John is well known for his great cows. Recently, the cows have decided to participate in the Incredible Cows Puzzle Contest (ICPC).

    Farmer John wants to divide the cows into two teams, and he wants to minimize the difference of Puzzle Solving Power of two teams.

    Puzzle Solving Power of a team is sum of Puzzle Solving Power of cows forming that team.

    Help F.J. to find the minimum difference!

    输入

    The first line of input consists of a single integer T, the number of test-cases. Each test-case consists of a line containing n (2 <= n <= 34), number of cows. n lines follow. i-th line contains the Puzzle Solving Power of i-th cow. Puzzle Solving Power of a cow is a non-negative number less than 10,000,000. There is a blank line between two consecutive test-cases.

    输出

    For each test-case, output a line containing the minimum difference which can be achieved.

    样例输入

    2
    3
    12
    6
    6

    10
    123
    455
    1000
    403
    234
    554
    129
    454
    84
    11

    样例输出

    0
    5

    题意

    把n数分成两堆,使得两堆和的差最小。

    题解

    n高达34,直接爆搜肯定不行。但是17可以直接爆搜(2^17)。

    于是乎,相当于把数组对半拆开,记和为suml和sumr,然后爆搜出两堆的所有情况。

    然后就是配对问题了,假设第一堆取出了X,第二堆取出了Y。

    答案是最小化函数|(X+Y)-((suml-X)+(sumr-Y))|,化简得到|2X+2Y-suml-sumr|。

    我们枚举一个未知数X,那么变成绝对值函数,易得Y>=(suml+sumr)/2-X,于是lower_bound找到最小的Y。

    这是最小值在右边的情况,还有在左的情况就是二分得到的Y前一个数。

    时间复杂度O(2^17*log(2^17))。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 ll a[35];
     6 set<ll>se[2];
     7 void dfs(int s,int t,bool f,ll sum)
     8 {
     9     if(s>t)
    10     {
    11         se[f].insert(sum);
    12         return;
    13     }
    14     dfs(s+1,t,f,sum+a[s]);
    15     dfs(s+1,t,f,sum);
    16 }
    17 int main()
    18 {
    19     int n,t;
    20     cin>>t;
    21     while(t--)
    22     {
    23         se[0].clear(),se[1].clear();
    24         cin>>n;ll suml=0,sumr=0;
    25         for(int i=1;i<=n/2;i++)cin>>a[i],suml+=a[i];
    26         for(int i=n/2+1;i<=n;i++)cin>>a[i],sumr+=a[i];
    27         dfs(1,n/2,0,0);dfs(n/2+1,n,1,0);
    28         ll min_abs=1e18;
    29         set<ll>::iterator it,itt;
    30         for(auto X:se[0])
    31         {
    32             it=se[1].lower_bound((suml+sumr)/2-X);
    33             itt=it;
    34             if(it!=se[1].begin())--itt;
    35             if(it==se[1].end())--itt,--it;
    36             min_abs=min(min_abs,min(abs(suml+sumr-2*X-2*(*it)),abs(suml+sumr-2*X-2*(*it))));
    37         }
    38         cout<<min_abs<<'
    ';
    39     }
    40     return 0;
    41 }
  • 相关阅读:
    docker 应用-1(安装以及基础命令)
    网桥原理及使用
    【年终总结】个人的2019年年终总结
    【bat批处理】批量执行某个文件夹下的所有sql文件bat批处理
    【实用工具】.fbr格式免费播放器 FBR格式 Free FlashBack Player
    【SQL骚操作】SqlServer数据库表生成C# Model实体类SQL语句
    【算法基础】面试过程中遇到的一些算法题输出杨辉三角
    【sql基础】按照名字分组查询时间最早的一条记录
    【面试题】java面试题整理(有空再贴答案)
    【海驾资料】海淀驾校科目三考试资料
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/11960263.html
Copyright © 2020-2023  润新知