题目:给定m种硬币,支付n元所需硬币最少个数。各面值课重复使用。
贪心算法从面值大的开始减。对于某些特殊问题不行
动态规划解题:
两个数组 C[m] 表示第i枚硬币的面值 T[m][n+1] 表示使用第i种硬币支付j元需要的最少硬币数
动态规划递归方程:
T[i][j] = min(T[i-1][j],T[i][j-C[i]]+1)
不使用第i枚硬币,此处解为前面支付j元的最优解T[i-1][j]。如果使用第i枚,此处的解为支付j-C[i]元的最优解加1;
优化:T[j] = min(T[j],T[j-C[i]]+1) ( 更新时只会在自己上一种硬币的最优解和减去自己面值的个数加一中选择)
#include<iostream>
#include<stdio.h>
using namespace std;
static const int MMAX = 20;
static const int NMAX = 50000;
static const int INFTY = (1<<20);
int main()
{
int n,m;
int C[21];
int T[NMAX +1];
cin >> n >> m;
for(int i=1;i<=m;i++){
cin >> C[i];
}
for(int i=0;i<=NMAX;i++) T[i] = INFTY;
T[0] = 0;
for(int i=1;i<= m;i++) {
for(int j=0;j+C[i] <= n;j++){
T[j+C[i]] = min(T[j+C[i]],T[j]+1);
}
}
cout << T[n] << endl;
return 0;
}