题目大意:
现有一个储蓄罐,空的时候重E,现里面装了一些硬币,总重变成了F(1 ≤ E ≤ F ≤ 10,000),现有N种硬币(1 ≤ N ≤ 500)对应了N种价值P和重量W(1 ≤ P ≤ 50,000,1 ≤ W ≤ 10,000,比如某种硬币价值P为10,重量W为20),现求储蓄罐中装的硬币的最小可能总价值。
现有多个测例(测例数题中给出),每个测例中都给出E、F、N以及N个P和W,现对每个测例求出可能的罐中的最小硬币总价值,如果达不到指定的重量则输出”This is impossible.“。
注释代码:
/*
* Problem ID : POJ 1384 Piggy-Bank
* Author : Lirx.t.Una
* Language : G++
* Run Time : 63 ms
* Run Memory : 392 KB
*/
#pragma G++ optimize("O2")
#include <stdio.h>
//总钱数的无穷,直接假设
#define INF 2100000000
//maximum number of coins
//硬币种类的最大数量
#define MAXCOINN 501
//maximum capacity
//罐子的最大容量
//大于10,000 - 1
#define MAXCAP 10000
#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
int p[MAXCOINN];//price[i]第i号钱币的价值
int w[MAXCOINN];//weight[i]第i号钱币的重量
//dp[i][j]表示第i号钱币装入容量为j的背包所获得的总价值
//完全背包问题是指有若干种物品装入一个背包,每种物品可以放任意多个
//然后求不超过背包容量情况下如何使价值达到最大或最小
//显然在这里是求最小值,所以有dp[i][j] = MIN( dp[i -1][j], dp[i - 1][ j - w[i] ] + p[i] )
//注意,在考虑将i放入背包这种情况(即后一种情况)时,不在是i - 1了!!!
//因为每种物品可以放任意多个,也许之前i已经放在过容量为j - w[i]的背包中过了
//所以不能忽略这种情形
//这里依然可以使用一维滚动数组,只不过动态规划的方向是正向的,而普通背包问题的方向是反向的
int dp[MAXCAP];
int
main() {
int t;//测例数
int e, f;//罐子的干重和鲜重
int cp;//capacity,罐子的容量
int n;//多少种硬币
int i, j;//计数变量
int tmp;//临时变量
scanf("%d", &t);
while ( t-- ) {
scanf("%d%d%d", &e, &f, &n);
cp = f - e;
//dp[0] = 0;//容量为0的背包价值为0,为全局变量直接初始化成0了
for ( i = 1; i <= cp; i++ )
dp[i] = INF;//由于是求最小值都初始化为无穷大
for ( i = 1; i <= n; i++ )
scanf("%d%d", p + i, w + i);
for ( i = 1; i <= n; i++ )
for ( j = w[i]; j <= cp; j++ ) {//注意是正向,从w[i]到cp
tmp = dp[ j - w[i] ] + p[i];
dp[j] = MIN( tmp, dp[j] );
}
if ( INF == dp[cp] )//表示现有硬币无法凑满整个罐子容量
puts("This is impossible.");
else
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[cp]);
}
return 0;
}
无注释代码:
#pragma G++ optimize("O2")
#include <stdio.h>
#define INF 2100000000
#define MAXCOINN 501
#define MAXCAP 10000
#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
int p[MAXCOINN];
int w[MAXCOINN];
int dp[MAXCAP];
int
main() {
int t;
int e, f;
int cp;
int n;
int i, j;
int tmp;
scanf("%d", &t);
while ( t-- ) {
scanf("%d%d%d", &e, &f, &n);
cp = f - e;
//dp[0] = 0;
for ( i = 1; i <= cp; i++ )
dp[i] = INF;
for ( i = 1; i <= n; i++ )
scanf("%d%d", p + i, w + i);
for ( i = 1; i <= n; i++ )
for ( j = w[i]; j <= cp; j++ ) {
tmp = dp[ j - w[i] ] + p[i];
dp[j] = MIN( tmp, dp[j] );
}
if ( INF == dp[cp] )
puts("This is impossible.");
else
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[cp]);
}
return 0;
}
单词解释:
piggy:n, 小猪; adj, 贪心的
irreversibly:adv, 不可逆地
reversible:adj, 可逆的,可撤销的
bound:n, 限制,约束,范围
sufficient:adj, 足够的,充足的
clearly:adv, 明显地,显然地
weigh:vt, 称重,权衡
currency:n, 货币
prematurely:adv, 过早地,早熟地
gram:n, 克(重量单位)
monetary:adj, 货币的,财政的