Description
Input
Output
Sample Input
3 10 110 2 1 1 30 50 10 110 2 1 1 50 30 1 6 2 10 3 20 4
Sample Output
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.思路:
一开始就知道是多重背包了,但是却想错方向,以为是价值的背包,结果总是想不出来。最后还是写了个关于个数的与重量相关的背包,发现了一个规律,能恰好装满必须是体积v的倍数才行,所以动态转移方程如下:
i=物品个数,j=变化的重量〉w,w=当前物品重量,
k=当前物品取多少个,v=物品价值
Dp[i][w]=min(dp[i-1][j],dp[i-1][j-k*w]+k*v);
其实物品个数只和以前有关,而且动态规划无滞后性,
所以可以省掉二维,利用滚动数组就行了,代码如下:
(时间很大:920ms,勉强过了)
AC代码:#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int T=10100; int dp[T]; void INIT(int v) { for(int i=0;i<=v;++i) { dp[i]=0x3f3f3f3f; } dp[0]=0; } int main() { int N,n,m,p,w,i,j,k,v; scanf("%d",&N); while(N--) { scanf("%d%d",&n,&m); v=m-n;INIT(v); scanf("%d",&n); for(i=0;i<n;++i) { scanf("%d%d",&p,&w); for(j=v;j>=w;--j) { for(k=1;k*w<=j;++k) { dp[j]=min(dp[j],dp[j-k*w]+k*p); } } } if(dp[v]!=0x3f3f3f3f) printf("The minimum amount of money in the piggy-bank is %d.\n",dp[v]); else printf("This is impossible.\n"); } return 0; }关于上面代码其实还可以优化一下,因为吴老师讲过了关于多重背包是可以降维的。上面的转移方程可以变为
Dp[i][j]=min(dp[i-1][j],dp[i][j-w]+v);
这样子明显是逆序是不行的了,因为他的i已不是i-1了,所以必须要知道了i后的值才能推出dp[i][j]。所以要顺序循环。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zsc2014030403015/article/details/46959709