1514: Packs
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4
[Submit][Status][Web Board]
Description
Give you n packs, each of it has a value v and a weight w. Now you should find some packs, and the total of these value is max, total of these weight is equal to m.
Input
First line is a number T( T ≤ 5) represent the test cases.
Then for each set of cases, first line is n (1 ≤ n ≤ 40) and m (1 ≤ m
< 2^31), follow n line each is Wi (1 ≤ Wi < 2^31) and Vi (-2^31
< Vi < 2^31).
Output
Each case a line for max value.(Each set of inputs to ensure the solvability)
Sample Input
2
3 3
1 1
2 2
3 4
5 2
1 -5
1 -8
1 0
1 -2
1 5
Sample Output
4
5
注意:这里要求是满足总重量必须固定,而不是接近总重量。这就成了直接折半枚举,map大法就行了。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <string> 6 #include <vector> 7 #include <set> 8 #include <map> 9 #include <stack> 10 #include <queue> 11 #include <sstream> 12 #include <iomanip> 13 using namespace std; 14 typedef long long LL; 15 const long long INF=99999999999999999LL; 16 const int EXP=1e-5; 17 const int MS=42; 18 19 map<LL,LL> mp; 20 int n; 21 LL W; 22 23 LL w[MS],v[MS]; 24 25 void solve() 26 { 27 mp.clear(); 28 int n1=n/2; 29 for(int i=0;i<(1<<n1);i++) 30 { 31 LL sw=0,sv=0; 32 for(int j=0;j<n1;j++) 33 { 34 if((i>>j)&1) 35 { 36 sw+=w[j]; 37 sv+=v[j]; 38 } 39 } 40 mp[sw]=max(mp[sw],sv); 41 } 42 LL ans=-INF; 43 for(int i=0;i< 1<<(n-n1);i++) 44 { 45 LL sw=0,sv=0; 46 for(int j=0;j<(n-n1);j++) 47 { 48 if((i>>j)&1) 49 { 50 sw+=w[n1+j]; 51 sv+=v[n1+j]; 52 } 53 } 54 if(mp.count(W-sw)) 55 ans=max(ans,mp[W-sw]+sv); 56 } 57 printf("%lld ",ans); 58 } 59 60 61 int main() 62 { 63 int T; 64 scanf("%d",&T); 65 while(T--) 66 { 67 scanf("%d%lld",&n,&W); 68 for(int i=0;i<n;i++) 69 scanf("%lld%lld",&w[i],&v[i]); 70 solve(); 71 } 72 return 0; 73 }
如果是重量不大于 W ,那么就要折半枚举+二分查找。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <stack> 11 #include <queue> 12 #include <sstream> 13 #include <iomanip> 14 using namespace std; 15 typedef long long LL; 16 const int INF=0x4fffffff; 17 const int EXP=1e-5; 18 const int MS=40; 19 20 int n; 21 LL W; 22 LL w[MS],v[MS]; 23 struct node 24 { 25 LL w,v; 26 bool operator <(const node &a) const //注意一定要加上const 27 { 28 return w<a.w||(w==a.w&&v<a.v); 29 } 30 }nodes[1<<(MS/2)]; 31 32 LL find(LL w,int cnt) 33 { 34 int l=0,r=cnt; 35 while(r-l>1) // 左闭右开区间处理起来更方便。 36 { 37 int mid=(l+r)/2; 38 if(nodes[mid].w<=w) 39 l=mid; 40 else 41 r=mid; 42 } 43 return nodes[l].v; 44 } 45 46 void solve() 47 { 48 int n1=n/2; 49 int cnt=0; 50 for(int i=0;i<(1<<n1);i++) 51 { 52 LL sw=0,sv=0; 53 for(int j=0;j<n1;j++) 54 { 55 if((i>>j)&1) 56 { 57 sw+=w[j]; 58 sv+=v[j]; 59 } 60 } 61 nodes[cnt].w=sw; 62 nodes[cnt++].v=sv; 63 } 64 sort(nodes,nodes+cnt); 65 int last=0; 66 for(int i=0;i<cnt;i++) 67 { 68 if(nodes[last].v<nodes[i].v) 69 { 70 nodes[++last]=nodes[i]; 71 } 72 } 73 cnt=last+1; 74 LL ans=0; 75 for(int i=0;i< 1<<(n-n1);i++) 76 { 77 LL sw=0,sv=0; 78 for(int j=0;j<(n-n1);j++) 79 { 80 if((i>>j)&1) 81 { 82 sw+=w[n1+j]; 83 sv+=v[n1+j]; 84 } 85 } 86 if(sw<=W) 87 { 88 LL tv=find(W-sw,cnt); 89 ans=max(ans,sv+tv); 90 } 91 } 92 printf("%lld ",ans); 93 } 94 95 96 int main() 97 { 98 int T; 99 scanf("%d",&T); 100 while(T--) 101 { 102 scanf("%d%lld",&n,&W); 103 for(int i=0;i<n;i++) 104 scanf("%lld%lld",&w[i],&v[i]); 105 solve(); 106 } 107 return 0; 108 }