最少硬币找零问题

Problem:

Give you the coins, and the total amount of money to change,find a solution for this change which minimize the number of coins needed.

Example:

Coins[] = {1,3,9,10};

Money = 15

Solution[] = {3,3,9}

分析:这道题类似于背包问题,背包问题的思路是,考虑第j个物品装入容量为j的背包中,此时有两只情况,j装得进去,j装不进去,然后推到出动态规划状态转移方程。对于这个问题,我们也可以用相同的思路来思考。

归纳(第一次尝试):假设已知如何解决money为i-1,硬币种类为j-1的子问题,记为P(i-1,j-1)。

接下来怎么办呢,如何推到出P(i,j)?在这样的归纳基础下面,我们不得不从i-1,j-1归纳出i,j来,也就是说我们在这个过程中同时对两个变量进行了归纳,这样会导致问题变得有些复杂,无从下手。(心得:如果在某一处卡住了,回头看看这个过程是否有漏洞;其次在读读题目,看看是否漏掉一些信息,题目的最终结果是求什么,怎么来表示这个结果。)

归纳(第二次尝试):假设已知如何解决P(i,j-1)。这个归纳就比上面那个好一些,而且容易思考下一步的问题,因为现在我们只要考虑第j种硬币,从而看看能否推导出P(i,j)。对于第j中硬币,我们有两种策略,一是使用第j种硬币不能使当前结果更优;二是使用第j种硬币能使当前结果更优,下面重点分析第二种情况。

现在问题变为要使用第j种硬币,那么该用多少呢?记Cj= i/j,这是单独使用第j种硬币需要的数量,Vj表示j的面值。接取Cj是最优的吗?怎样证明这样不行?

设Rj = i-Cj*Vj,使用Cj后剩余的money;设Qj= i-(Cj-1)*Vj, 使用Cj-1个硬币后剩余的money此时Qj = Rj + Vj。那么接下来找零Rj使用的硬币一定比找零Qj的硬币少吗?这个不一定,因为Rj相比Qj跟小,这个意味着需要更多的零钱。比如Rj=2,Qj=12,此时都需要两个硬币(1,1和3,9),而最终结果是开始选择Cj-1比选择Cj的少一个。所以在这里,应当全面的考察由1,2,…Cj的情况。

P(i,j-1)=MIN{ P(i,j-1),P(i-k*Vj,j-1)+k}(k=1,2,…Cj)


参考代码:

有些动态规划的中间结果不需要多维数组来存放,有些情况只需要一维数组即可,知道如何写和自己动手写出来,得到的信息不一样,唯有动手才能体会更多

int leastnums(int coins[], int numcoin,int money) { if(numcoin < 1 || money < 0 || coins[0] > money) return -1; int *res = new int[money+1]; //初始化,只用第一个硬币 for(int i = 1; i < money+1; ++i) res[i] = money / coins[0]; for(int j = 1; j < numcoin; ++j) { for( int i = coins[j]; i < money+1; ++i) { int k = i / coins[j]; if( i%coins[j]==0) { res[i] = k; continue; } while(k) { int left = i - k*coins[j]; if(res[left]+k < res[i]) res[i] = res[left]+k; --k; } }//end for }//end for return res[money]; } int _tmain(int argc, _TCHAR* argv[]) { int coins[]={1,3,9,10}; int lnum = leastnums(coins,4,22); return 0; }

总结:动态规划还可以在优化吗?动态规划有一个变形,叫备忘录法。备忘录法也是用一个表格来保存已解决的子问题的答案,并通过记忆化搜索来避免计算一些不可能到达的状态。其实在写动态规划code过程中,有些地方也可以进行改进和优化,并非没一个动态规划都可以优化。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值