Piggy-Bank HDU - 1114(题解)

原题

原题链接

题目大意

题目是讲有一个储钱罐,给出空罐时重量E,目前罐的重量F,已知罐里硬币的种类,有n种,每一种都给出其价值p[i]和重量w[i],问该罐里至少有多少钱?如果硬币不能刚好凑够该重量则输出-1.

题目解析

为了讲题方便,我把题目空罐时质量换成m0,目前罐的重量换成m,价值改成v[i].这道题可以转换为一个等效的问题,就是给定硬币种类,每种硬币有无限个,问能否从这些硬币中刚好凑成重量为m-m0的硬币堆,如果能凑的话价值之和要尽可能小.稍微思考后会发现这就是完全背包问题,只是稍微变动而已.首先设一个dp数组,dp[i]表示i重量时硬币价值之和的最小值.(初始化为INF),dp[0]=0,dp[i]=INF表示这些硬币不能凑到刚好i重量,然后一遍外循环用i=1→n遍历所有物品,内循环从j=w[i]→(m-m0)(内循环这样更新能体现出一种硬币有无限个的特点)if(dp[j-w[i]]!=INF) dp[j]=min(dp[j],dp[j-w[i]]+v[i])来不断更新dp数组,最后如果dp[m-m0]不是INF,输出dp[m-m0],否则输出-1即可.(j之所以从w[i]开始是为了防止j-w[i]越界,对这个dp还是不太清楚的话可以在草稿纸模拟这个dp数组的更新过程)

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <string>
 8 #include <utility>
 9 #include <queue>
10 #include <stack>
11 const int INF=0x3f3f3f3f;
12 using namespace std;
13 
14 int dp[10001];
15 int w[501],v[501];
16 
17 int main()
18 {
19     int t;
20     cin>>t;
21     while(t--)
22     {
23         memset(dp,INF,sizeof(dp));
24         memset(w,0,sizeof(w));
25         memset(v,0,sizeof(v));
26         int m0,m,n;
27         cin>>m0>>m>>n;
28         m-=m0;
29         for(int i=1;i<=n;i++)
30         cin>>v[i]>>w[i];
31         dp[0]=0;
32         for(int i=1;i<=n;i++)
33         for(int j=w[i];j<=m;j++)
34         if(dp[j-w[i]]!=INF)    dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
35         if(dp[m]!=INF) cout<<"The minimum amount of money in the piggy-bank is "<<dp[m]<<'.'<<endl;
36         else cout<<"This is impossible."<<endl;
37     }
38     return 0;
39 }

 

posted @ 2019-02-25 19:39  VBL  阅读(206)  评论(0编辑  收藏  举报