时间限制:1 秒 内存限制:32 兆
题目描述:
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金 n 元,而市场有 m 种大米,每种大米都是袋装产品, 其价格不等,并且只能整袋购买。请问:你用有限的资金最多能采购多少公斤粮食呢?
输入:
输入数据首先包含一个正整数 C,表示有 C 组测试用例,每组测试用例的第一行是两个整数 n 和 m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是 m 行数据,每行包含 3 个数 p ,h 和 c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应 种类大米的袋数。
输出:
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
样例输入:
1 8 2 2 100 4 4 100 2
样例输出:
400
解题思路:
典型的多重背包问题,重点在于拆分物品数量。另外,本题的金额相当于物品体积,重量相当于物品价值。
示例代码:
#include<cstdio> int max(int a, int b){return a > b ? a : b;}//取最小值函数 struct Thing { int w; int v; }list[2001]; int dp[101]; int main() { int T;//测试组数 scanf("%d", &T); int s, n;//总金额和大米种类 while(T--) { scanf("%d%d", &s, &n); int cnt = 0;//拆分后的物品总数 for (int i = 1; i <= n; i++) { int v, w, k; scanf("%d%d%d", &w, &v, &k); int c = 1; while (k - c > 0)//对输入的数字k,拆分成1,2,4...k-2^c+1,c为使最后一项大于0的最大整数 { k -= c; list[++cnt].w = c * w; list[cnt].v = c * v;//这才存到list里,变成0-1背包问题 c *= 2; } list[++cnt].w = k * w; list[cnt].v = k * v; } for (int i = 1; i <= s; i++)dp[i] = 0;//初始化 for (int i = 1; i <= cnt; i++)//对拆分后的物品进行0-1背包 { for (int j = s; j >= list[i].w; j--) { dp[j] = max(dp[j], dp[j - list[i].w] + list[i].v); } } printf("%d ", dp[s]); } return 0; }