P - Consumer
题目叙述
FJ is going to do some shopping, and before that, he needs some boxes to carry the different kinds of stuff he is going to buy. Each box is assigned to carry some specific kinds of stuff (that is to say, if he is going to buy one of these stuff, he has to buy the box beforehand). Each kind of stuff has its own value. Now FJ only has an amount of W dollars for shopping, he intends to get the highest value with the money.
输入
The first line will contain two integers, n (the number of boxes 1 <= n <= 50), w (the amount of money FJ has, 1 <= w <= 100000) Then n lines follow. Each line contains the following number pi (the price of the ith box 1<=pi<=1000), mi (1<=mi<=10 the number goods ith box can carry), and mi pairs of numbers, the price cj (1<=cj<=100), the value vj(1<=vj<=1000000)
输出
For each test case, output the maximum value FJ can get
样例输入
3 800
300 2 30 50 25 80
600 1 50 130
400 3 40 70 30 40 35 60
样例输出
210
解题思路
这题是一个依赖性的背包问题,你要是买这一件物品时你只有先买放这件物品的盒子才可以,因此我们在买一件物品时我们首先要判断买完这件物品的钱够不够买盒子,够的话就转化为了0-1背包的问题,就是放与不放进背包的问题了,还有对于每一件盒子都要进行0-1背包的算法,因此需要一个二维数组或者两个一维数组。不用二维数组是因为要减少内存和缩短运行时间
代码如下:
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5 + 7;
int dp[N];
int temp[N];
int max(int x,int y) {
return x > y ? x : y;
}
int main() {
int t , n , m1,m,m2,v;
while(~scanf("%d%d",&t,&n)) {
memset(dp,0,sizeof(dp));
memset(temp,0,sizeof(temp));
for(int i = 1; i <= t; i++){
scanf("%d%d",&m1,&m);
for(int j = 0;j < m1;j++)
dp[j] = -1; //判断买完这件物品,够不够买盒子
for(int j = m1; j <= n; j++)
dp[j] = temp[j - m1]; //降维操作
for(int k = 1; k <= m;k++) {
scanf("%d%d",&m2,&v);
for(int j = n;j >= m2;j--)
if(dp[j - m2] != -1) {
dp[j] = max(dp[j],dp[j - m2] + v); //0-1背包求解
}
}
for(int j = 0; j <= n; j++) {
temp[j] = max(temp[j],dp[j]); //判断这个盒子时买还是不买
}
}
printf("%d\n",temp[n]);
}
return 0;
}