01背包变种 第k解问题 hdu 2639

先说说普通01包的状态问题吧

普通的01背包,在状态转移的过程中为了求出最优解,一定是遍历了所有的情况 然后再求的最优解。那么对于第k最优解问题,我们只需要再加一个维度,用来记录每一个状态k优解的状态就好了。

在普通背包过程中 每次的选举的状态为dp[i-1][j],dp[i-1][j-c[i]+w[i]  为了求解最优情况 我们一般是对这两个状态取最大值 然后依次遍历 得到最大值。那么,为了得到第k大的解,我们就需要另外使用数组来对两种状态的所有值记录下来 然后选取第k大的情况

上代码

#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
    int val[101],vol[101],dp[1001][33];
    int aa[33],bb[33];
    int n,v,k,t;
    cin>>t;
    while(t--)
    {
        cin>>n>>v>>k;
        for(int i=1;i<=n;i++) cin>>val[i];
        for(int i=1;i<=n;i++) cin>>vol[i];
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            for(int j=v;j>=vol[i];j--)//将 每次优化的k种解记录下来
            {
                int z;
                for(z=1;z<=k;z++)
                {
                    aa[z]=dp[j][z];
                    bb[z]=dp[j-vol[i]][z]+val[i];
                }
                aa[z]=bb[z]=-1;
                int p,pp,ppp;
                p=pp=ppp=1;
                while(p<=k+1&&(aa[pp]!=-1||bb[ppp]!=-1))//加一个去重的过程
                {
                    if(aa[pp]>bb[ppp])     dp[j][p]=aa[pp++];
                    else dp[j][p]=bb[ppp++];
                    if(dp[j][p]!=dp[j][p-1]) p++;
                }
            }
        }
        cout<<dp[v][k]<<endl;
    }
    return 0;

}

第k解的问题 让我对背包问题的最优化过程有了一个了解
时间: 2024-10-10 06:46:00

01背包变种 第k解问题 hdu 2639的相关文章

HDU 2639 01背包求第k大

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3718    Accepted Submission(s): 1903 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took par

HDU - 2639(01背包求第K大值)

传送门 题意:it will be a strictly decreasing sequence from the 1st maximum , 2nd maximum .. to the K-th maximum.  If the total number of different values is less than K,just ouput 0. 输入:T组数据 体积V 要求的K    N , V, K(N <= 100 , V <= 1000 , K <= 30) 各项价值 各项

2639-Bone Collector II (01背包之第k优解)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 求第k优解的关键代码: 用两个数组记录两种状态(选择或不选择),并且只要记录前k次.在这两个数组中都是前k次可能的最优解.所以我们只要把这两个数组做比较,一直排到k就行了 题目代码: 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int dp

HDU 3466(01背包变种

http://acm.hdu.edu.cn/showproblem.php?pid=3466 http://www.cnblogs.com/andre0506/archive/2012/09/20/2695841.html 这道题多了一个限制条件Qi,低于Qi时不能购买. 解题思路是看更新量,因为限制条件限制的是更新量. 比如一个物品是5 9,一个物品是5 6,对第一个进行背包的时候只有dp[9],dp[10],…,dp[m],再对第二个进行背包的时候,如果是普通的,应该会借用前面的dp[8],

HDU 5543 Pick The Sticks:01背包变种

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5543 题意: 给你N个金条和一张长度为L的桌子.每个金条长度为a[i],价值为w[i].金条只能在桌子上横着摆一排,并且只要金条的重心(中心)在桌子上,就可以放.问你在桌子上能够摆的金条的最大总价值. 题解: 首先表示状态: 考虑到第i个金条,在这之前已经占用了j的长度,在k个端点摆了金条.即:dp[i][j][k] 如何转移(逆推): 对于第i个金条,有三种决策:摆在桌子中央.摆在桌子端点处.不摆

poj 1837 天平问题(01背包变种)

题意:给你n个挂钩,m个砝码,要求砝码都用上,问有多少中方案数 题解:对于这道题目的状态,我们定义一个变量j为平衡度,当j=0的时候,表明天平平衡.定义dp[i][j]表达的含义为使用前n个砝码的时候,平衡度为j的方案数.计数类型的背包,更新的时候把每个砝码的所有可能贡献(每个砝码可以放在不同的钩子上,每个钩子的离中点的距离不一致)都updata一下就ok了.关键是状态的抓取,然后这个计数背包的理解. ac代码: #include <cstdio> #include <iostream&

【背包专题】A - Bone Collector II hdu2639 【01背包的第k个最优解】

The title of this problem is familiar,isn't it?yeah,if you had took part in the "Rookie Cup" competition,you must have seem this title.If you haven't seen it before,it doesn't matter,I will give you a link: Here is the link: http://acm.hdu.edu.c

(01背包)Buy the souvenirs (hdu 2126)

http://acm.hdu.edu.cn/showproblem.php?pid=2126 Buy the souvenirs Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1904    Accepted Submission(s): 711 Problem Description When the winter holiday

HDU3466(01背包变种)

Proud Merchants Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4219    Accepted Submission(s): 1740 Problem Description Recently, iSea went to an ancient country. For such a long time, it was