30. 贪心算法
一、什么是贪心算法
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,贪心算法并不从整体最优上加以考虑,它所做出的选择只是在某种意义上的局部最优解。贪心算法的基本思路是从问题的某一个初始解出发,然后一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,它的选取应该满足局部优化的条件。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。贪心算法的可行性需要满足两个要素:所求问题的整体最优解可以通过一系列局部最优的选择(即贪心选择)来达到;问题的最优子结构性质是该问题可用贪心算法求解的关键特征。
总的来说,贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即贪心)的选择,从而希望导致结果是全局最好或最优的算法。
贪心算法所得到的结果不一定是最优的结果,但是都是相对接近最优解的结果。
二、零钱兑换问题
零钱兑换问题主要涉及到如何将一定金额的钱兑换成零钱,并且通常希望以最少的硬币或纸币数量来完成兑换。这个问题在日常生活中非常常见,比如消费者在购物后收到的找零,或者需要将大面额钞票换成零钱的情况。
解决零钱兑换问题,可以采用以下几种方法:
- 贪心算法:这是一种直观且简单的策略,其基本思想是从最大面额的硬币或纸币开始,尽可能多地使用这些大面额零钱进行兑换,然后逐渐使用较小面额的零钱,直到兑换完所需的全部金额。然而,贪心算法并不总是能够得到最优解,即使用最少的硬币或纸币数量。在某些特定的面额组合下,贪心算法可能会陷入局部最优而非全局最优。
- 动态规划:当贪心算法无法得出最优解时,可以考虑使用动态规划。动态规划通过把原问题分解为相对简单的子问题,并保存子问题的解来避免重复计算,最终推导出原问题的最优解。在零钱兑换问题中,可以设定一个数组来保存每个金额对应的最少硬币数量,并从小到大逐步计算出每个金额的最优解。
- 回溯法:对于更复杂的情况,特别是当硬币或纸币的面额组合不规则时,可以采用回溯法来尝试所有可能的兑换组合。回溯法通过递归地尝试不同的兑换方式,并在发现当前方式不可行时回退到上一步,直到找到可行的最优解。
#include <stdio.h>
void GreedyCoinChange(int coins[], int coin_kind, int amount);
int main()
{
int amount = 0;
int coins[] = {5, 2 , 1}; // 硬币面值数组,从大到小排列
int coin_kind = sizeof(coins) / sizeof(coins[0]); // 硬币种类数
printf("请输入要兑换的金额数: ");
scanf("%d", &amount);
if (amount >= 0)
{
GreedyCoinChange(coins, coin_kind, amount); // 调用贪心找零函数
} else
{
printf("输入的金额数不能为负数\n");
}
return 0;
}
/**
* @brief 贪心算法零钱兑换问题
*
* @param coins 硬币面值数组
* @param coin_kind 硬币种类数
* @param amount 兑换的金额数
*/
void GreedyCoinChange(int coins[], int coin_kind, int amount)
{
int remainingAmount = amount; // 剩余需要找零的金额
int coinCount[coin_kind]; // 用于记录每种硬币的数量
for (int i = 0; i < coin_kind; i++)
{
coinCount[i] = 0; // 初始化硬币数量为0
}
for (int i = 0; i < coin_kind; i++) // 遍历硬币面值,从大到小尝试找零
{
while (remainingAmount >= coins[i])
{
coinCount[i]++; // 增加该面值硬币的数量
remainingAmount -= coins[i]; // 减去已找零的金额
}
if (remainingAmount == 0)
{
break; // 找到足够的硬币后退出循环
}
}
// 打印找零结果
printf("兑换的金额数: %d\n", amount);
for (int i = 0; i < coin_kind; i++)
{
if (coinCount[i] > 0)
{
printf("面值为 %d 的硬币的个数为 %d\n", coins[i], coinCount[i]);
}
}
}