zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Android Button四种点击事件和长按事件
    Android 简单登陆 涉及 Button CheckBox TextView EditText简单应用
    Android EditText属性
    Android-TextView 控件常用属性以及基本用法
    对象数组空指针异常
    数字反转问题
    遇3问题
    队列解密QQ号
    线程先后执行问题
    小哼买书
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/11960263.html
Copyright © 2011-2022 走看看