题目
给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1.
样例一
输入:
1, 2, 5
11
输出: 3
解释: 11 = 5 + 5 + 1
1
2
3
4
5
样例二
输入:
2
3
输出: -1
思路
1.确定状态
·开一个数组,数组的每个元素f[i]或者f[i][j]代表什么;
·最后一步:一定有一枚最后的硬币ak,除掉这一枚硬币其余的为27-ak;
关键1:不知道k-1枚硬币怎么拼出27-ak的,不知道ak和k,但是确定前面的硬币拼出来27-ak;
关键2:因为是最优策略,所以拼出27-ak的硬币数一定要少;
·子问题:最少用多少枚硬币可以拼出27-ak
简化定义,设状态f(X)=最少用多少枚硬币拼出X;
如果ak为2、5、7,f(27)=f(27-x)+1;
最少的硬币数:f(27)=min{f(27-2)+1,f(27-5)+1;f(27-7)+1};
递归解法:
2. 转移方程
·设状态f[X]=最少用多少枚硬币拼出X;
·对于任意X,f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1};
3.舒适条件和边界情况
·f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1};
·X-2,X-5,X-7小于0:如果不能拼出Y,就定义f[Y]=正无穷,f[1]=min{f[-1]+1,f[-4]+1,f[-6]+1};
·初始条件(用转移方程算不出来,需要手工定义):f[0]=0;
4.计算顺序
·拼出X所需要的最少硬币数:f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1};
·初始条件:f[0]=0;
·然后计算f[1],f[2]...f[27];
·当我们计算到f[X]时,f[X-2],f[X-5],f[X-7]已经得到了
递推:
#include<iostream>
#include<cstdio>
#include<algorithm>
int f[30];
using namespace std;
int main()
{
int coin1,coin2,coin3,n;
cin>>coin1>>coin2>>coin3;
cin>>n;
f[0]=0;
int Max=n/coin1+1;
for(int i=1;i<=n;i++)
{
int zero,one,two;
if(i>=coin1)
zero=f[i-coin1]+1;
else
zero=Max;
if(i>=coin2)
one=f[i-coin2]+1;
else
one=Max;
if(i>=coin3)
two=f[i-coin3]+1;
else
two=Max;
f[i]=min(zero,min(one,two));
}
cout<<f[n];
return 0;
}