【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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章