问题描述:
输入总金额n,硬币不同价值的种类m,m种硬币的面值;
例如:15 6
1 2 7 8 12 50
输出凑成n最少的硬币数
(1)贪心算法:
每次都选择面值最大的。问题在于,求出来的并不是最优解,上例中,用贪心解出来的结果为3(1,2,12),而实际为2(7,8)
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int a[m];
for(int i=0;i<m-1;i++)
cin>>a[i];
sort(a,a+m);
int count=0;
for(int i=m-1;i>=0;)
{
if(a[i]<=n)
{
count++;
if(a[i]==n)
break;
else
n=n-a[i];
}
else i--; //每一硬币可以重复使用
}
cout<<count;
}
(2)动态规划
dp[j] 代表目标为j元的时候,需要的硬币数量
状态转移方程 dp[j+a[i]]=min(dp[j+a[i]],dp[j]+1) 代表选择当前硬币面值为a[i]时,放或者不放,找出数量最小的一个
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int a[m+1];
for(int i=1;i<=m;i++)
cin>>a[i];
sort(a,a+m);
int dp[n+1];
for(int i=0;i<n+1;i++)
dp[i]=i; //初始化
for(int i=1;i<=m;i++)
for(int j=0;j+a[i]<=n;j++)
dp[j+a[i]]=min(dp[j+a[i]],dp[j]+1);
//for(int i=1;i<=n;i++)
//cout<<dp[i]<<" ";
cout<<dp[n];
}