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.
 
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;
}

 

posted @ 2020-02-22 22:04  remarkableboy  阅读(287)  评论(0编辑  收藏  举报