acm常用技巧四 超大背包问题
来源:互联网 发布:领流量软件 编辑:程序博客网 时间:2024/05/22 04:38
一.超大背包问题
pair<LL,LL> ps[1<<(MXN/2)];void Fun(){ int n2=n/2; for(int i=0;i<1<<n2;++i){ LL sw=0,sv=0; for(int j=0;j<n2;++j) if(i>>j&1){ sw+=w[j]; sv+=v[j]; } ps[i]=make_pair(sw,sv); } sort(ps,ps+(1<<n2)); int m=1; for(int i=1;i<1<<n2;++i) if(ps[m-1].second<ps[i].second) ps[m++]=ps[i]; LL res=0; for(int i=0;i<1<<(n-n2);++i){ LL sw=0,sv=0; for(int j=0;j<n-n2;++j){ if(i>>j&1){ sw+=w[n2+j]; sv+=v[n2+j]; } } if(sw<=W){ LL tv=(lower_bound(ps,ps+m,make_pair(W-sw,INF))-1)->second; res=max(res,sv+tv); } } printf("%lld\n",res);}
二.坐标离散化
int compress(int x1[],int x2[],int w){ vector<int> xs; for(int i=0;i<N;++i) for(int d=-1;d<=1;++d){ int tx1=x1[i]+d,tx2=x2[i]+d; if(1<=tx1&&tx1<=W) xs.push_back(tx1); if(1<=tx2&&tx2<=W) xs.push_back(tx2); } sort(xs.begin(),xs.end()); xs.erase(unique(xs.begin(),xs.end()),xs.end()); for(int i=0;i<N;++i){ x1[i]=find(xs.begin(),xs.end(),x1[i])-xs.begin(); x2[i]=find(xs.begin(),xs.end(),x2[i])-xs.begin(); } return xs.size();}void Fun(){ W=compress(X1,X2,W); H=compress(Y1,Y2,H); memset(fld,0,sizeof(fld)); for(int i=0;i<N;++i) for(int y=Y1[i];y<=Y2[i];++y) for(int x=X1[i];x<=X2[i];++x) fld[y][x]=1; int ans=0; for(int y=0;y<H;++y) for(int x=0;x<W;++x){ if(fld[y][x]) continue; ans++; queue<pair<int,int> > que; que.push(make_pair(x,y)); while(!que.empty()){ int sx=que.front().first,sy=que.front().second; que.pop(); for(int i=0;i<4;++i){ int tx=sx+dx[i],ty=sy+dy[i]; if(tx<0||W<=tx||ty<0||H<=ty) continue; if(fld[ty][tx]) continue; que.push(make_pair(tx,ty)); fld[ty][tx]=true; } } } printf("%d\n",ans);}