选硬币:
 现有面值分别为1角1分,5分,1分的硬币,请给出找1角5分钱的最佳方案。
#include <iostream>
#include <vector>
std::vector<int> findChange(int amount) {
    std::vector<int> coins = {11, 5, 1}; // 按面值从大到小排序的硬币面值
    std::vector<int> result(coins.size(), 0); // 用于存储每种硬币的数量
    for (int i = 0; i < coins.size(); i++) {
        int numCoins = amount / coins[i]; // 计算当前硬币面值的数量
        result[i] = numCoins; // 存储数量
        amount -= numCoins * coins[i]; // 更新剩余金额
    }
    return result;
}
int main() {
    int amount = 15; // 需要找零的金额,单位为分
    std::vector<int> change = findChange(amount);
    std::cout << "找零方案为:" << std::endl;
    std::cout << "1角1分硬币数量:" << change[0] << std::endl;
    std::cout << "5分硬币数量:" << change[1] << std::endl;
    std::cout << "1分硬币数量:" << change[2] << std::endl;
    
    return 0;
}
一开始我想的很简单,以为是简单的求整除数。
 但要是你仔细一想,这肯定是不对的,不是所有问题都能用贪心。
 在求最优的过程中,贪心和动态规划一直是一对冤家,到底选择哪个,难道了很多英雄好汉,所以最好的方式就是具体问题具体分析,只有结合实际情况才能选出最适合问题的算法。
 我们都知道贪心的局限性,只能求出其中一个解的,但是不是最优需要考量。
 让我们来看一下用上面贪心求出来的解:
 
 但这肯定不是最优解,我们在找零的时候遵循的规则是用最少的钱张数交给别人,这样才方便。
 所以最佳找零方案为:
 1角1分硬币数量:0
 5分硬币数量:3
 1分硬币数量:0
 让我们来看看用动态规划写出来的代码:
#include <iostream>
using namespace std;
const int N = 10005;
const int INF = 0x3f3f3f3f; 
int f[N], a[N];
int main() {
    int n, w;
    cin >> n >> w;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= w; i++) {
        f[i] = INF;
    }
    
    for (int i = 0; i < n; i++) {
        for (int j = a[i]; j <= w; j++) {
            f[j] = min(f[j], f[j - a[i]] + 1);
        }
    }
    if (f[w] == INF) {
        cout << -1; 
    } else {
        cout << f[w];
    }
    return 0;
}

 结果和我们预期的完全一样
总结
选硬币在动态规划中是一种叫状态表示的题型,通常用一维/二维的数组组成状态转移方程,通过更新数组来达到获取最优解的目标


















