1111: 松哥的困惑II
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 125 Solved: 54
[Submit][Status][Web Board]
Description
松哥历尽千辛万苦终于找到女朋友了,但是一星期后又回到了单身的日子,松哥很生气后果很严重,所以松哥决定大吃一顿,但是由于松哥很胖,他要吃m千克的东西才会饱,松哥喜欢吃n样东西,每份东西有ai千克,需要bi元钱,只有ci份.松哥希望知道最少需要花多少钱才能使他吃饱,你能告诉他嘛.东西只能一份一份买,不能只买半份.
Input
多组测试数据.
每组测试数据的第一行包含两个正整数n,m(n<=100,m<=10000).
第二行有n个正整数a1,a2,a3,a4…an-1.(ai<=10000)
第三行有n个正整数b1,b2,b3,b4…bn-1.(bi<=100)
第四行有n个正整数c1,c2,c3,c4…cn-1.(ci<=100)
Output
对于每组数据输出能使松哥吃饱所需要花费最少的钱.如果松哥吃完了所有的东西还不能吃饱,请输出“impossible”.
Sample Input
3 1
1 1 2
1 2 1
1 1 1
3 100
1 1 2
1 2 1
1 1 1
2 2
2 1000
2 10
2 2
2 5
2 1000
2 10
2 2
Sample Output
1
Impossible
2
10
HINT
Source
【解析】
多重背包
就是从放背包变成了吃东西而已。但是此题唯一需要注意的就是,背包不能超出V,但是此题值要求吃饱。所以可以超出,但是即使超出也要放在record[v]中。
状态转移方程:
record[j+k*value[i]]=min(record[j+k*value[i]],record[j]+k*weight[i]);
#include <bits/stdc++.h>
using namespace std;
const int maxn = 11000;
int main()
{
int weight[maxn], value[maxn], record[maxn], c[maxn];
int n, v;
while (~scanf("%d%d", &n, &v))
{
int sum = 0, num = 0;
for (int i = 0; i < n; i++)
scanf("%d", &value[i]);
for (int i = 0; i < n; i++)
scanf("%d", &weight[i]);
for (int i = 0; i < n; i++)
{
scanf("%d", &c[i]);
num += weight[i] * c[i];
sum += c[i] * value[i];
}
if (sum < v)printf("Impossible\n");
else
{
for (int i = 1; i <= v; i++)record[i] = num;
record[0] = 0;
for (int i = 0; i < n; i++)
for (int j = v - 1; j >= 0; j--)
if (record[j] != num)
for (int k = 1; k <= c[i]; k++)
{
if (j + k * value[i] >= v)
record[v] = min(record[v], record[j] + k * weight[i]);//此处注意
else
record[j + k * value[i]] = min(record[j + k * value[i]], record[j] + k * weight[i]);
}
printf("%d\n", record[v]);
}
}
return 0;
}