题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3449
题意:
有n个箱子,总共有多少money,箱子的价格为pi元,箱子价值为0,每个箱子里装有mi个物品,每个物品价格cj元价值vj元,要买该箱子里的物品,必须得买了该箱子,求在那么多的money下,最多能买到多少价值的物品。
Sample Input
3 800
300 2 30 50 25 80
600 1 50 130
400 3 40 70 30 40 35 60
Sample Output
210
解析:背包问题,但是加了条件,必须得买了该箱子才能买箱子里的物品,作为新手的我,刚开始学背包问题,把我搞得够呛!
首先设置一个总的dp[]数组,再设置一个用来记录上一状态的中间数组temp[],
一层一层的做,也就是说求完一个箱子的最大价值后再求下一个箱子的最大价值,每一层对总的dp[]进行更新,到最后一层完成后,也就知道总的最大价值了,具体看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int dp[100005],temp[100005];
int box,money;
while(scanf("%d %d",&box,&money)!=EOF)
{
memset(dp,0,sizeof(dp));//先对dp[]置0
int pi,mi,cj,vj;
for(int i=1;i<=box;i++)
{
scanf("%d %d",&pi,&mi);
for(int i=0;i+pi<=money;i++)//用中间数组temp[]记录上一状态的最大价值,箱子价值为0,所以只需简单继承
temp[i+pi]=dp[i];//这个转化关系式要理解透彻
for(int i=1;i<=mi;i++)//对箱子里的每一个物品进行01背包的求最大价值
{
scanf("%d %d",&cj,&vj);
for(int j=money;j>=pi+cj;j--)
temp[j]=max(temp[j],temp[j-cj]+vj);//这里都是用中间数组temp[]在进行记录
}
for(int i=pi;i<=money;i++)//当一层算完后,也就是一个箱子算完后,用更新后中间记录数组temp[]与记录
dp[i]=max(dp[i],temp[i]);//前一状态数组dp[]进行比较,更新dp[]数组,完成后进行下一个箱子的计算
}
printf("%d\n",dp[money]);//最后输出那么多money的最大价值
}
return 0;
}