在 ACM 能夠開展之前,必須准備預算,並獲得必要的財力支持。該活動的主要收入來自於 Irreversibly Bound Money (IBM)。思路很簡單。任何時候,某位 ACM 會員有少量的錢時,他將所有的硬幣投入到小豬儲錢罐中。這個過程不可逆,因為只有把小豬儲錢罐打碎才能取出硬幣。在足夠長的時間之后,小豬儲錢罐中有了足夠的現金,用於支付 ACM 活動所需的花費。
但是,小豬儲錢罐存在一個大的問題,即無法確定其中有多少錢。因此,我們可能在打碎小豬儲錢罐之后,發現里面的錢不夠。顯然,我們希望避免這種不愉快的情況。唯一的可能是,稱一下小豬儲錢罐的重量,並嘗試猜測里面的有多少硬幣。假定我們能夠精確判斷小豬儲錢罐的重量,並且我們也知道給定幣種的所有硬幣的重量。那么,我們可以保證小豬儲錢罐中最少有多少錢。
你的任務是找出最差的情形,即判斷小豬儲錢罐中的硬幣最少有多少錢。我們需要你的幫助。不能再貿然打碎小豬儲錢罐了!
輸入
輸入包含 T 組測試數據。輸入文件的第一行,給出了 T 的值。
對於每組測試數據,第一行包含 E 和 F 兩個整數,它們表示空的小豬儲錢罐的重量,以及裝有硬幣的小豬儲錢罐的重量。兩個重量的計量單位都是 g (克)。小豬儲錢罐的重量不會超過 10 kg (千克),即 1 <= E <= F <= 10000 。每組測試數據的第二行,有一個整數 N (1 <= N <= 500),提供了給定幣種的不同硬幣有多少種。接下來的 N 行,每行指定一種硬幣類型,每行包含兩個整數 P 和 W (1 <= P <= 50000,1 <= W <=10000)。P 是硬幣的金額 (貨幣計量單位);W 是它的重量,以 g (克) 為計量單位。
輸出
對於每組測試數據,打印一行輸出。每行必須包含句子 “The minimum amount of money in the piggy-bank is X.” 其中,X 表示對於給定總重量的硬幣,所能得到的最少金額。如果無法恰好得到給定的重量,則打印一行 “This is impossible.” 。
示例輸入
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.
#include<iostream> #include<cstdio> #include<algorithm> #define INF 100000000 using namespace std; const int N=1E5; int dp[N]; int w[N]; int price[N]; int main(){ int t; cin>>t; while(t--){ int n,m; cin>>n>>m; int nn=m-n; for(int i=0;i<=nn;i++){ dp[i]=INF; } int mm; cin>>mm; for(int i=1;i<=mm;i++){ cin>>price[i]>>w[i]; } dp[0]=0;//這一步是特別重要的。 for(int i=1;i<=n;i++){ for(int j=w[i];j<=nn;j++){ dp[j]=min(dp[j],dp[j-w[i]]+price[i]); } } if(dp[nn]==INF) printf("This is impossible.\n"); else printf("The minimum amount of money in the piggy-bank is %d.\n",dp[nn]); } return 0; }
總結:
背包問題的恰好裝滿問題:
在一些背包問題中要求會從不超過背包最大容量變為恰好裝滿背包,與前者的差別在於初始化的不同
1. 在恰好裝滿的情況下取最大值:
把dp[maxn]全賦值為-INF
dp[0]=0;
如果dp[n]==-INF,則在容量為n時,背包無法裝滿。
恰好裝滿的dp[n]有一個具體值,而不是-INF
2.在恰好裝滿的情況下去最小值:
把dp[maxn]全賦值為INF
dp[0]=0;
如果dp[n]==INF,則在容量為n時,背包無法裝滿。
恰好裝滿的dp[n]有一個具體值,而不是INF.
滿包問題:http://www.360doc.com/content/20/0325/09/69169653_901520769.shtml