【dp - 多重揹包】575: Coin Changing

題目:
http://acm.swust.edu.cn/#/problem/575/490
題目描述
設有n 種不同面值的硬幣,各硬幣的面值存於數組T[1:n]中。現要用這些面值的硬幣來找錢。可以使用的各種面值的硬幣個數存於數組Coins[1:n]中。 對於給定的1≤n≤10,硬幣面值數組T和可以使用的各種面值的硬幣個數數組Coins,以及錢數m,0≤m≤20001,編程計算找錢m的最少硬幣數。

輸入
第一行中只有1 個整數給出n的值,第2 行起每行2 個數,分別是T[j]和Coins[j]。最後1 行是要找的錢數m。

輸出
最少硬幣數,無解時輸出-1

樣例輸入
3
1 3
2 3
5 3
18
樣例輸出
5

說明:
這道題可以用多重揹包來解決,多重揹包的思路就是一次可以取給定數量個物品的01揹包。不過這道題目將硬幣面值看作體積,然後找出裝滿揹包總體積的最小硬幣個數。故需要將dp數組初始化爲inf,dp[0]的初值賦爲0。至於無解情況,若最終狀態能轉移到dp[sum](sum代表找錢數m),則一定有解。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=20005;
const int inf=0x3f3f3f3f;
int t[maxn],coin[maxn],dp[maxn];
int n,sum;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>t[i]>>coin[i];
	cin>>sum;
	for(int i=0;i<maxn;i++){
		dp[i]=inf;
	}
	dp[0]=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=coin[i];j++){
			for(int k=sum;k>=t[i]*j;k--){
				dp[k]=min(dp[k],dp[k-t[i]*j]+j); //枚舉裝k件物品i的狀態轉移
			}
		}
	}
	if(dp[sum]==inf){
		cout<<-1<<endl;
	}else{
		cout<<dp[sum]<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章