hdu2639(背包求第k优解)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2639

题意:给出一行价值,一行体积,让你在v体积的范围内找出第k大的值

分析:dp[i][j][k]表示前i个物品容积为j时的第k优解。那么对于每种状态dp[i][j]都需要维护好前k优解。

每次根据前k优解进行每种取或不取第i件物品,用数组a记录取第i件物品,数组b记录不取,这样

数组a,b了所有能组成j的x种解,最后在x里取前k优解记录下来就好。剩下的肯定不是前k优解了。。。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 10010
using namespace std;
int p[110],w[110],dp[1010][50],a[50],b[50];
int main()
{
    int t,n,v,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&v,&k);
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++)scanf("%d",&p[i]);
        for(int i=1; i<=n; i++)scanf("%d",&w[i]);
        for(int i=1; i<=n; i++)
        {
            for(int j=v; j>=w[i]; j--)
            {
                for(int l=1; l<=k; l++)//组成体积为j无非就是j-w[i]状态加上第i件和不取第i件,最多有2k种
                {
                    a[l]=dp[j-w[i]][l]+p[i];
                    b[l]=dp[j][l];
                }
                a[k+1]=-1;
                b[k+1]=-1;
                int x,y,z;
                x=y=z=1;
                while(z<=k&&(a[x]!=-1||b[y]!=-1))//在最多2k种里取最大的k个解并有序存入
                {
                    if(a[x]>b[y])
                    {
                        dp[j][z]=a[x];
                        x++;
                    }
                    else
                    {
                        dp[j][z]=b[y];
                        y++;
                    }
                    if(dp[j][z]!=dp[j][z-1])z++;
                }
            }
        }
        printf("%d\n",dp[v][k]);
    }
}

时间: 2024-10-22 10:45:56

hdu2639(背包求第k优解)的相关文章

01背包之求第K优解——Bone Collector II

http://acm.hdu.edu.cn/showproblem.php?pid=2639 题目大意是,往背包里赛骨头,求第K优解,在普通01背包的基础上,增加一维空间,那么F[i,v,k]可以理解为前i个物品,放入容量v的背包时,第K优解的值.时间复杂度为O(NVK). Talk is cheap. 看代码吧. import java.util.Scanner; public class BoneCollector { public static void main(String[] sur

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

背包的第k优解[动态规划]

From easthong ☆背包的第k优解                 描述 Description     DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包.这些包的容量是相同的,都是 V.可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值. 在 DD 看来,合理的背包安排方案是这样的: 1. 每个人背包里装的物品的总体积恰等于包的容量.  2. 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品.  3. 任意两个人,他们包里的物品清单

[JZOJ P1281] [DP]背包的第k优解

@kaike 传送门 看了半天,不会写 没见过这种题型,看了背包九讲,然而只有很简单的几句话 我认为就是多加了一维,变成三维数组 由于必须恰好等于包的容量,所以要赋最小值 然而不能那样递推为什么我也不知道 还没悟出来 嗯加油 1 #include<iostream> 2 using namespace std; 3 long f[51][50001]; 4 int q1[51]; 5 int q2[51]; 6 int main() 7 { 8 int k,v,n; 9 int value,w

HDU 2639 (01背包第k优解)

/* 01背包第k优解问题 f[i][j][k] 前i个物品体积为j的第k优解 对于每次的ij状态 记下之前的两种状态 i-1 j-w[i] (选i) i-1 j (不选i) 分别k个 然后归并排序并且去重生成ij状态的前k优解 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 1010 using namespace std; int T,n,m,k,c[maxn],v[maxn

01背包 HDU 2639,第K优解

只要每次都保存前k优解就可以了 注意当价值一样时,只算一种,所以要进行去重复 的操作 用到了unique, 1 2 2 4 0 0 unique之后1 2 4 0 0 2 Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2433    Accepted Submission(s): 1277 Prob

DP2_第K优解

转载:http://m.blog.csdn.net/blog/a511310132/13465985 对于求次优解.第K优解类的问题,如果相应的最优解问题能写出状态转移方程.用动态规划解决,那么求次优解往往可以相同的复杂度解决,第K优解则比求最优解的复杂度上多一个系数K.其基本思想是将每个状态都表示成有序队列,将状态转移方程中的max/min转化成有序队列的合并.这里仍然以01背包为例讲解一下.首先看01背包求最优解的状态转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c

HDU 2639 Bone Collector II (DP 第k优解)

题意:输入t,t组测试样例,每组样例输入 n, v, k. 接着输入n个物品的价值,再输入n个物品的体积.求k优解. 分析:dp[n][v][k]表示n个物品,在体积不超过v的情况,第k大的值是多少.dp[i][v][k]与dp[i-1][v][k]与dp[i-1][v-volume[i]]+value[i]有关. #include <iostream> #include <cstdio> #include <cstring> #include <algorith

第k优解 hdu 2639

#include<iostream> #include<cstdio> #include<cstring> #define maxn 110 using namespace std; int w[110],v[110],f[1010][110],a[110],b[110]; //f[j][k]表示重量为j时的第k优解 int main() { int t; scanf("%d",&t); while(t--) { int n,m,i,j,k,