01背包第k最优解
附题目链接:Bone Collector II
Input
The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, K(N <= 100 , V <= 1000 , K <= 30)representing the number of bones and the volume of his bag and the K we need. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Followed by T cases , each case three lines , the first line contain two integer N , V, K(N <= 100 , V <= 1000 , K <= 30)representing the number of bones and the volume of his bag and the K we need. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
One integer per line representing the K-th maximum of the total value (this number will be less than 231).
Sample Input
3
5 10 2
1 2 3 4 5
5 4 3 2 1
5 10 12
1 2 3 4 5
5 4 3 2 1
5 10 16
1 2 3 4 5
5 4 3 2 1
Sample Output
12
2
0
最开始我想简单了,我以为只要把每一步记录下来然后排序就行,发现连样例都过不了.先把我的蒟蒻(错误的)思路粘一发,看看有多少老铁和我想的一样哈哈哈
#include<iostream> #include<cstring> #include<list> #include<algorithm> using namespace std; int dp[1000][1000]; int w[1000]; int v[1000]; int sot[1000]; int n,maxa; int x,maxv,k; list<int> l; int main() { cin>>n; while(n--) { cin>>x>>maxv>>k; for(int i=1; i<=x; i++) cin>>w[i]; for(int i=1; i<=x; i++) cin>>v[i]; for(int i=1; i<=x; i++) for(int j=0; j<=maxv; j++) { if(j>=v[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]); else dp[i][j]=dp[i-1][j]; l.push_back(dp[i][j]); l.push_back(dp[i-1][j-v[i]]+w[i]); } l.sort(); l.unique(); list<int>::iterator it; int p=0; for(it=l.end(); it!=l.begin(); it--) { p++; if(p==k+1) { cout<<*it<<endl; break; } } memset(dp,0,sizeof(dp)); l.clear(); } return 0; }
好了,下面进入正解,平时写背包用dp[i]表示容量为i时的最优解,那么自然可以想到用dp[i][j]表示容量为i时的第j优解,
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; int dp[1005][50],d1[50]; int main() { int t; scanf("%d",&t); while(t--) { int n,m,k; int w[105],v[105]; memset(dp,0,sizeof(dp)); scanf("%d%d%d",&n,&m,&k); for(int i=1; i<=n; i++) scanf("%d",&v[i]); for(int i=1; i<=n; i++) scanf("%d",&w[i]); for(int i=1; i<=n; i++) for(int j=m; j>=w[i]; j--) { int cnt=0; for(int q=1; q<=k; q++) { d1[cnt++]=dp[j][q]; d1[cnt++]=dp[j-w[i]][q]+v[i]; } sort(d1,d1+cnt); int p=1; for(int q=cnt-1; q>=0; q--) { if(p>k)break; if(q==cnt-1||d1[q]!=d1[q+1]) dp[j][p++]=d1[q]; } } printf("%d\n",dp[m][k]); } return 0; }