1. 程式人生 > >qwb和李主席

qwb和李主席

stream put pan 枚舉 ios void output 最小 air

qwb和李主席

Time Limit: 4 Sec Memory Limit: 128 MB

Description

qwb和李主席打算平分一堆寶藏,他們想確保分配公平,可惜他們都太懶了,你能幫助他們嘛?

Input

輸入包含多組測試數據,處理到文件結束。

每組測試數據的第一行是一個正整數N(0 <= N <=36 )表示物品的總個數.。

接下來輸入N個浮點數(最多精確到分),表示每個物品的價值V(0<V<=1e9)。

Output

對於每組測試數據,輸出能夠使qwb和李主席各自所得到的物品的總價值之差的最小值(精確到分),每組測試數據輸出占一行。

Sample Input

3 0.01 0.1 1
2 1 1

Sample Output

0.89
0.00
分析:n很小v很大的情況下不能背包;
   考慮折半搜索,枚舉其中一半,然後在另一半中二分即可;
   註意浮點數*200倍變偶數取整的技巧;
代碼:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include 
<string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #include<unordered_map> #define rep(i,m,n) for(i=m;i<=n;i++) #define mod 1000000007 #define
inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") const int maxn=5e4+10; const int N=5e2+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;} int n,m,k,t; ll a[1<<18],b[1<<18],c[18],d[18]; void gao(ll d[],ll a[],int num) { for(int i=0;i<(1<<num);i++) { d[i]=0; for(int j=0;j<num;j++) { if(i>>j&1) { d[i]+=a[j]; } } } } int main() { int i,j; while(~scanf("%d",&n)) { int cnta=0,cntb=0; ll sum=0; rep(i,1,n) { double x; scanf("%lf",&x); ll y=round(x*200); //(ll)(x*200+0.1); sum+=y; if(i<=n/2)c[cnta++]=y; else d[cntb++]=y; } gao(a,c,cnta); gao(b,d,cntb); cnta=(1<<cnta); cntb=(1<<cntb); sort(b,b+cntb); ll ret=1e18; rep(i,0,cnta-1) { int pos=lower_bound(b,b+cntb,sum/2-a[i])-b; if(pos<cntb)ret=min(ret,abs(sum-2*(a[i]+b[pos]))); if(pos-1>=0)ret=min(ret,abs(sum-2*(a[i]+b[pos-1]))); } printf("%.2f\n",ret/200.0); } return 0; }

qwb和李主席