HDU 3449—— Consumer有依赖的背包

题目大意:

购物,买相应物品之前必须先买能装相应物品的盒子,现在已知n个盒子的价钱,以及每个盒子能装的物品数,以及这些物品的价值和花费。为w钱下能买到物品的最大价值。



思路:背包。首先很容易想到的一个状态转移方程是:


DP[i][j]=MAX{DP[i-1][j],MAX{DP[i-1][j-k]+Pack[i][k]}}。其中

DP[i][j]表示前i个盒子中,在金钱j下所能得到的最大价值。考虑第i个盒子选和不选,以及选的话分配多少钱给i。

然而很明显上述时间复杂度过高。考虑优化。仔细分析,会发现MAX{DP[i-1][j-k]+Pack[i][k]},


实际上表示的是在金钱j下且一定考虑第i个盒子下的最大价值。将盒子的价值看作0,在金钱j下首先将盒子的价钱考虑进去。那么剩下的只是挑选i盒子中的物品,即01背包。令f(i,j)为前i个盒子中且第i个盒子必须考虑时在金钱j下的

所得最大价值。那么该初始值f(i,j)=DP[i-1][j-Pbox[i]]+0;初始值确定以后(相当于已经忽略了盒子的影响)。那么直接背包即可。

——————转载


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define M 100001
int dp[51][M],n;
int main()
{
    int n,v;
    while(scanf("%d%d",&n,&v)!=EOF){
        memset(dp,-1,sizeof dp);
        memset(dp[0],sizeof dp[0]);
        for(int i=1;i<=n;++i){
            int x,p;
            scanf("%d%d",&x,&p);
            for(int j=x;j<=v;++j) dp[i][j]=dp[i-1][j-x];
            while(p--){
                int c,w;
                scanf("%d%d",&c,&w);
                for(int j=v;j>=c;--j){
                    if(dp[i][j-c]!=-1){
                        dp[i][j]=max(dp[i][j],dp[i][j-c]+w);
                    }
                }
            }
            for(int j=0;j<=v;++j){
                dp[i][j]=max(dp[i][j],dp[i-1][j]);
            }
        }
        cout<<dp[n][v]<<endl;
    }
    return 0;
}

相关文章

什么是设计模式一套被反复使用、多数人知晓的、经过分类编目...
单一职责原则定义(Single Responsibility Principle,SRP)...
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强...
适配器模式将一个类的接口转换成客户期望的另一个接口,使得...
策略模式定义了一系列算法族,并封装在类中,它们之间可以互...
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,...