http://acm.hdu.edu.cn/showproblem.php?pid=1114
这几天是我们队的dp训练日,dp很难是因为他很抽象,转换方程不容易找到。
就像上面这道题目,看过一遍后的第一直觉就像是0-1背包问题,但仔细想象它与背包问题不同之处是它的每件物品的数量是无限的……,很烦躁~~经过肥庄的指点,明白了可以结合母函数来做,可是普通的母函数都是3个for,也就是O(n3)的复杂度,似乎不能直接做。后又经过大叔和肥庄狂轰滥炸似的指导,加上自己2个小时的公式推导,终于看到了红红的AC,嘿,不容易啊~
Code
1 #include<iostream>
2 #include<limits.h>
3 using namespace std;
4 int dp[10010];
5 int main()
6 {
7 int t,e,f,n,i,j,k,values;
8 int p[501],w[501];
9 scanf("%d",&t);
10 while(t--)
11 {
12 scanf("%d %d",&e,&f);
13 values=f-e;
14 scanf("%d",&n);
15 for(i=1;i<=n;i++)
16 {
17 scanf("%d %d",&p[i],&w[i]);
18 }
19 memset(dp,-1,sizeof(dp));
20 dp[0]=0;
21 for(i=1;i<=n;i++)
22 {
23 for(j=w[i],k=0;j<=values;j++)
24 {
25 if(dp[j]==-1)
26 {
27 if(dp[j-w[i]]!=-1)
28 dp[j]=dp[j-w[i]]+p[i];
29 }
30 else
31 {
32 if(dp[j-w[i]]!=-1)
33 {
34 if(dp[j-w[i]]+p[i]<dp[j])
35 dp[j]=dp[j-w[i]]+p[i];
36 }
37
38 }
39 }
40 }
41 if(dp[values]==-1)
42 printf("This is impossible.\n");
43 else
44 printf("The minimum amount of money in the piggy-bank is %d.\n",dp[values]);
45 }
46 return 0;
47 }