题目:有重量和价值分别为wi和vi的n个物品。从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
1<=n<=40
1<=wi,vi<=10^15
1<=W<=10^15
输入:
4
2 1 3 2
3 2 4 2
5
输出:
7(挑选0,1,3号)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 10000;
int n;
ll w[MAXN];
ll v[MAXN];
ll W;
pair<ll,ll> ps[1 << (MAXN/2)];
bool cmp(const pair<ll,ll> &a,const pair<ll,ll> &b ){
if(a.first==b.first)
return a.second<b.second;
return a.first<b.first;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&w[i]);
}
for(int i=0;i<n;i++){
scanf("%d",&v[i]);
}
scanf("%d",&W);
int n2 = n/2;
for(int i=0;i< 1<<n2 ;i++){
ll sw=0; ll 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]<ps[i]){
ps[m++] = ps[i];
}
}
ll res= 0;
for(int i=0;i<1<<(n-n2);i++){
ll sw =0; ll 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),cmp)-1)->second;
res = max(res,sv+tv);
}
}
printf("%lld\n",res);
return 0;
}