超大背包问题
2017-03-04 22:17
267 查看
#include<iostream> #include<math.h> #include<algorithm> #include<stdio.h> #define INF 10000000 typedef long long ll; using namespace std; int n; ll w[41],v[41],W; pair<ll,ll> ps[1<<21]; int main() { cin>>n; for(int i=0;i<n;i++) { cin>>w[i]>>v[i]; } cin>>W; //枚举前半部分 二进制枚举 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(j>>i&1) { sw+=w[n2+j]; sv+=v[n2+j]; } } if(sw<=W) { //找到前半部分中加起来不超重的价值最大者 ll tv=(lower_bound(ps,ps+m,make_pair(W-sw,(ll)INF))-1)->second; res=max(res,sv+tv); } } cout<<res<<endl; return 0; }
View Code