要求:

有n种硬币,面值分别为v1,v2,v3,,,,,vn,数量无限。输入非负整数n,选用硬币,使其和为n,要求输出最少的硬币组合。
这里假设n=5,其它情况也一样的。

准备工作

假设只有5种面值的硬币:1,5,10,25,50
tepy[5]={1,5,10,25,50}每种硬币的面值
mi[i]:表示金额为i最少需要多少个硬币
path[i]:表示金额为i需要的最后一个硬币的面额,便于后面输出方案,方案里一定有path[i],下一个一定是path[i-path[i]],因为path一定会保证当前最优

思路:

状态:mi[i]:表示金额为i最少需要多少个硬币
mi[i]=mi[i-tepy[j]]+1;表示金额i可以由金额i-tepy[j]加上一块面额为tepy[j]的硬币得到

代码:

#include<bits/stdc++.h>
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int type[5]={1,5,10,25,50};//所有面值的硬币 
int mi[251];                //每个数值需要的最小硬币数
int path[251];                //每个数值需要的最后一个硬币面值 
void solve() {
    for(int i=1;i<251;++i)    //初始化 
        mi[i]=300;
    mi[0]=0;
    for(int i=0;i<5;++i) 
    for(int j=type[i];j<251;++j)
        if(mi[j]>mi[j-type[i]]+1) {
            path[j]=type[i];      //在每个金额上记录路径,即金币的面值 
            mi[j]=mi[j-type[i]]+1;//递推式 
        }
}
void print(int s) {
    while(s) {
        cout<<path[s]<<" ";
        s-=path[s];
    }
    cout<<endl;
}//打印硬币组合 
int n;
int main() {
    js;
    solve();
    while(cin>>n) {
        cout<<mi[n]<<endl;
        print(n);
    }
    return 0;
}