标签:思维二分
Time Limit: 30000MS | Memory Limit: 65536K | |
Total Submissions: 1562 | Accepted: 261 |
Description
Input
Output
Sample Input
1 10 3 20 100 -100 0
Sample Output
10 1 0 2
Source
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<algorithm> #include<cmath> #include<map> #define ll long long using namespace std; const int maxn=1000005; int n,m,p; ll a[35]; struct node { ll val; int len; } nod1[maxn],nod[maxn]; //map <ll,int> mq; //主要控制存在数里面存最小的 int erfen(ll x) { int l=0,r=p-1,mid; while(r>=l) { mid=(l+r)>>1; if(nod[mid].val>=x) r=mid-1; else l=mid+1; } return l; } int cmp(node p1,node p2) { if(p1.val<p2.val) return 1; if(p1.val==p2.val&&p1.len<p2.len) return 1; return 0; } int main() { int i; int x,s,res; ll ans; while(cin>>n&&n) { for(i=0; i<n; i++) cin>>a[i]; ans=1e15+5,res=50; m=n/2; //前面用来枚举,后面用来二分. //mq.clear(); s=1<<(n-m); for(x=1; x<s; x++) //建立二分数据库 { int tt=x; ll tmp=0; int cnt=0; for(i=m; i<n; i++) { if(tt&1) { tmp+=a[i]; cnt++; } tt>>=1; } nod1[x].val=tmp; nod1[x].len=cnt; } sort(nod1+1,nod1+s,cmp); nod[0].val=0; nod[0].len=0; nod[1].val=nod1[1].val; nod[1].len=nod1[1].len; p=2; for(i=2;i<s;i++) { if(nod1[i].val!=nod[p-1].val) { nod[p].val=nod1[i].val; nod[p++].len=nod1[i].len; } } sort(nod,nod+p,cmp); //for(i=0;i<p;i++) //cout<<nod[i].val<<" "<<nod[i].len<<" eh"<<endl; s=1<<m; for(x=0; x<s; x++) { ll tt=x,tmp=0; int cnt=0; for(i=0; i<m; i++) { if(tt&1) { tmp+=a[i]; cnt++; } tt>>=1; } int pos=erfen(-tmp); int pos1=max(pos-1,0),pos2=min(pos+1,p-1); for(i=pos1; i<=pos2; i++) { ll tmp1=nod[i].val+tmp; int tmp2=nod[i].len+cnt; if(tmp1==0&&tmp2==0) continue; //不能什么都不取 if(tmp1<0) tmp1=-tmp1; if(tmp1<ans||(tmp1==ans&&tmp2<res)) { ans=tmp1; res=tmp2; } } } cout<<ans<<" "<<res<<endl; } return 0; } /* 1 10 3 20 100 -100 5 5 4 1 2 3 5 5 4 -2 -2 3 0 */
POJ 3977Subset(枚举+二分),布布扣,bubuko.com
标签:思维二分
原文地址:http://blog.csdn.net/coraline_m/article/details/26385375