• 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;
    }
  • 相关阅读:
    c++ ShellExecuteEx调用java打包的exe程序
    麻省理工学院公开课-第四讲:快速排序 及 随机化 算法
    Win10的IIS与以前版本的一个区别
    干就行了!!!写程序就像珊瑚,分支太多,哪有那么多复用!
    NPoco的使用方法
    为什么前端要写标准代码?
    对于委托、事件、观察者模式最一目了然的代码段
    delphi处理消息的几种方式
    哎呀妈呀,吓死我了,幸好服务器没崩溃。
    Delphi的Hint介绍以及用其重写气泡提示以达到好看的效果
  • 原文地址:https://www.cnblogs.com/iloveysm/p/12347528.html
Copyright © 2020-2023  润新知