动态规划基础

贪心法解决硬币问题缺陷

在最少硬币问题中,贪心法的操作是:每次都选出最大的硬币,从大到小的进行整除.然而这种方法带有缺陷,例如硬币面值比较奇怪,1,2,4,5,6支付9元,贪心的出结论是6,2,1三个硬币,然后正确答案却是5,4.

判断标准是任意面值硬币大于比它小的所有硬币之和.我的理解是满足这个定理时,因为硬币足够大,可以覆盖到其它更小的硬币,从而确保每次选择都是局部最优的。不满足时可能会在选择硬币时会选择ci,导致需要3枚硬币,但如果选择ci-1可能再加个ci-2就能得到解了.

动态规划解决硬币问题

定义数组int Min[Money] 表示每个金额所需最少硬币数量,如何递推的计算硬币数量呢?

5种面值: 1 5  10 25 50

方法1(错误的):Min[0]=0 (0元不需要硬币) Min[1]=1 ...Min[5]=2(5个1元 1个5元) 我想只要将所有的少一个这种类型的情况相加不就行了吗 代码如下

int type[] = { 1,5,10,25,50 };
void solve(int num )
{
    vector<int>Min(num + 1,0);
    Min[0] = 0; Min[1] = 1;
    for (int i = 2; i <= num; i++)
    {
        for (int j = 0; j < sizeof(type) / sizeof(int); j++)
        {
            if (i < type[j])
                break;
            Min[i] += Min[i - type[j]] ;
        }
    }
}

但当遍历到6时出了问题 Min[6]+=Min[1],Min[6]+=Min[5]--->Min[6]=3 但我们知道结果应该是2啊(6个1 1个1+1个五)

原因分析: Min[6]+=Min[1]时表示1个1+1个五  Min[6]+=Min[5]时表示 6个1和 1个1+1个五,这样的话有些情况就会多次计算

方法二:从面值入手,从小到大考虑每种面值的最优解

void solve2(int num)
{
    vector<int>Min(num + 1, 0);
    Min[0] = 0; Min[1] = 1;
    for (int j = 0; j < sizeof(type) / sizeof(int); j++)
    {
    for (int i = 2; i <= num; i++)
    {
       
            if (i < type[j])
                break;
            Min[i] = min(Min[i - type[j]] + 1,Min[i]);
    }
    }
}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值