硬币找零(动态规划)
问题介绍
给定指定的硬币种类,面值为 1, 3, 5(在此具体化些),给定所找零的钱数 sum,给出最少的硬币找零数,每个种类的硬币无限使用。
问题分析
看到这问题,当时我想到用贪心算法来求解,最后求解方案因为巧合对了,后来在网上看到动态规划的题目,才知道贪心算法得不到最优解,比如 给定 面值为 1, 3, 4,给定找零数为 6,用贪心法得出方案 [4,1,1],但显然 [3,3] 方案即可。分析下问题,想一下若存在最少硬币数 num 满足当前给定的找零数 sum,则是不是一定存在最少硬币数 num-1 满足找零数 sum - (1, 3, 5 )?答案是存在,想一想就知道,当然边界除外。这个类似于最短路径的 dijkstra算法。
实现方案
对于上面这个思路的实现方案,我用的是回溯思想,撸一个递归函数,不断递归查找给定硬币数,给定金额的方案。在此设置一个标志位 is_find ,若找到 赋值为 true 。在外面套一层循环使得 硬币数 从 1 不断增加,若找不到则 硬币数 + 1 继续找,若找到 则退出循环(通过判断 is_find ), 找的过程中需要保存数据,在此声明一个数组变量 coin_kind 保存方案,每次递归将下标为 num 的数组元素设置为 当前选择的硬币值,这是回溯的思想,具体看代码。
代码
#include<stdio.h>
#include<stdlib.h>
int coin[3] = {1, 3, 5}; /* 硬币种类 */
int coin_kind_num = 3; /* 硬币种类数量 */
int sum = 7; /* 找零钱数 */
int min_coin_num; /* 硬币最少数 */
int coin_kind[1000]; /* 存放最少数的方