题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1114
Piggy-Bank
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5033 Accepted Submission(s): 2479
But there is a big problem with piggy-banks. It is not possible to determine how much money is inside. So we might break the pig into pieces only to find out that there is not enough money. Clearly, we want to avoid this unpleasant situation. The only possibility is to weigh the piggy-bank and try to guess how many coins are inside. Assume that we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. Then there is some minimum amount of money in the piggy-bank that we can guarantee. Your task is to find out this worst case and determine the minimum amount of cash inside the piggy-bank. We need your help. No more prematurely broken pigs!
3 10 110 2 1 1 30 50 10 110 2 1 1 50 30 1 6 2 10 3 20 4
The minimum amount of money in the piggy-bank is 60. The minimum amount of money in the piggy-bank is 100. This is impossible.
先分析题目的意思。这个题目的意思是有一只存钱的小猪灌,告你它空着的时候的重量,以及满着的时候的重量。然后有一些钱币,每种钱币都有自己的价值和重量。每种钱币可以使用任意的次数。现在题目的要求就是要你把这个储钱罐装满,但是里面装的钱币的价值要是最少的。这就和我们以前做过的完全背包问题相反了。怎么做呢?很简单。就是状态转移方程f[j]在赋初值的时候全部赋成正无穷大,表示在j背包容量下什么都不装所能达到的最小价值为正无穷,也就是一个无效的背包。但是f[0]要赋作0,因为在0背包容量下你什么都不能放进去,则最小的当然是0,是一个有效的状态。而整个背包的总容量就是用满重量的容量减去空的时候的容量。再根据完全背包的算法求出装满情况下最少的价值。如果最后f[V]为无效状态的话,则代表,这个背包根本就不能装满,那说明在所给的条件下是无法满足要求的,输出“This is impossible.”。如果不是,则说明存在最小值,则输出。完全背包思想详见:http://love-oriented.com/pack/P02.html
#include<iostream>
using namespace std;
#define MAX 10010
#define INF 999999999
int f[MAX]; //f[j]表示的是在j容量下装满时的最小价值,若为无穷大,则表示无法装满,状态无效
int value[MAX];
int weight[MAX];
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
int solve(int n,int V)
{
int i,v;
for(i=1;i<=n;i++) //采用的是完全背包算法
{
for(v=weight[i];v<=V;v++)
{
f[v] = min(f[v],f[v-weight[i]]+value[i]); //这就是常规题型不同的地方,是在有效的情况下求最小
}
}
return f[V];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int pig,fullpig;
scanf("%d%d",&pig,&fullpig);
int n;
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
{
scanf("%d%d",&value[i],&weight[i]);
}
for(i=1;i<=fullpig-pig;i++) //初始化,很重要
f[i] = INF;
f[0] = 0;
int ans = solve(n,fullpig-pig);
if(ans >= INF) //如果最大容量是一个无效的状态,也就是无法装满的情况
printf("This is impossible.\n");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",ans);
}
return 0;
}

被折叠的 条评论
为什么被折叠?



