HDU 1114 Piggy-Bank (dp问题之完全背包问题)
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1114
思路:动态规划之完全背包问题
题目分析:给出了钱罐开始的重量e和装满后的重量f,然后给你n种硬币,每个价值为p,重量为w,求出最小的价值使钱罐的重量恰好为w
如果不存在 输出This is impossible.
状态转移方程:f[v]=min{f[v],f[v-w[i]]+p[i]}
注意:一道简单的完全背包题(于0-1背包就是第二个for循环倒过来就行了)
,要求做的仅仅是求最小值,而不是最大值,那么只要对初始化进
行一些改变就可以了。把f[0]赋值为0,其他赋值为无穷大。
这个题目的意思是有一只存钱的小猪灌,告诉你它空着的时候的重量,以及满着的时候的重量。然后有一些钱币,每种钱币都有自己的价值和重量。每种钱币可以使用任意的次数。现在题目的要求就是要你把这个储钱罐装满,但是里面装的钱币的价值要是最少的。这就和我们以前做过的完全背包问题相反了。怎么做呢?很简单。就是状态转移方程f[j]在赋初值的时候全部赋成正无穷大,表示在j背包容量下什么都不装所能达到的最小价值为正无穷,也就是一个无效的背包。但是f[0]要赋作0,因为在0背包容量下你什么都不能放进去,则最小的当然是0,是一个有效的状态。而整个背包的总容量就是用满重量的容量减去空的时候的容量。再根据完全背包的算法求出装满情况下最少的价值。如果最后f[V]为无效状态的话,则代表,这个背包根本就不能装满,那说明在所给的条件下是无法满足要求的,输出“This is impossible.”。如果不是,则说明存在最小值,则输出。完全背包思想详见:http://love-oriented.com/pack/P02.html
代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define INF 0xfffffff 4 int dp[10010]; 5 int min(int x,int y) 6 { 7 return x>y?y:x; 8 } 9 int main() 10 { 11 int t,e,f,n,m,p,w,i,j; 12 scanf("%d",&t); 13 while(t--) 14 { 15 scanf("%d%d",&e,&f); 16 m=f-e; 17 for(i=1;i<=m;i++) 18 dp[i]=INF; dp[0]=0; //这点的初始化表示不太懂,有待进一步的研究。。。 19 scanf("%d",&n); 20 for(i=0;i<n;i++) 21 { 22 scanf("%d%d",&p,&w); 23 for(j=w;j<=m;j++) //与01背包相比倒过来 24 { 25 dp[j]=min(dp[j],dp[j-w]+p); 26 } 27 } 28 if(dp[m]==INF) 29 printf("This is impossible.\n"); 30 else 31 printf("The minimum amount of money in the piggy-bank is %d.\n",dp[m]); 32 } 33 system("pause"); 34 return 0; 35 }