zoukankan      html  css  js  c++  java
  • 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
    ",dp[m][k]);
        }
        return 0;
    }
  • 相关阅读:
    bzoj 4548 小奇的糖果
    CF1151F Sonya and Informatics
    loj 2392「JOISC 2017 Day 1」烟花棒
    loj 2336「JOI 2017 Final」绳
    luogu P3620 [APIO/CTSC 2007]数据备份
    bzoj 4771 七彩树
    CF765F Souvenirs
    bzoj 3145 [Feyat cup 1.5]Str
    luogu P4482 [BJWC2018]Border 的四种求法
    第五章例题
  • 原文地址:https://www.cnblogs.com/iloveysm/p/12347528.html
Copyright © 2011-2022 走看看