动态规划之硬币问题

有若干币值为1元、3元、5元的硬币,问得到11块钱最少需要几枚硬币。咋一看,用一眼望穿法就可知道是3枚,但我们要用程序来实现它。
就像做证明题一样,我们将这个问题细分,从最简单的得到1元需要几枚硬币开始分析,很显然coinValue(1)=1,只需要拿一个1元硬币即可。(若从0元算起,则有coinValue(0) = 0),要得到2元,我们只有1元面值的硬币可选择,我们先拿一个1元的硬币,还剩下一元面值,从coinValue(1)=1可得到coinValue(2)=coinValue(1)+1,要得到3元,有1元和3元两种面值的硬币可供选择,假设,我们先拿一枚1元的,则还剩2元,即coinvalue(3)=coinValue(2)+1,假设先拿一枚3元的硬币,则剩下0元,即coinvalue(3)=coinValue(0)+1(这里的+1,代表的是先拿的那一枚硬币),两种取法取最小值coinValue(3)=min{coinValue(2)+1,coinValue(0)+1},由此可推,coinValue(i)=coinValue(i-vj)+1,i代表要得到的钱,vj表示第j枚取走的硬币的面值。因为存在多种取法,所以要取所有方法中的最小值。可以看出,这里存在递归。
先贴段递归的代码:

C#代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BubbleSort
{
    class Program
    {
        static void Main(string[] args)
        {

            int count = 0;
            int re = CoinSort(11,ref count);
            Console.WriteLine("得到11枚硬币至少需要:" + re+"枚硬币,执行的次数:"+count);
            Console.ReadLine();
        }
        public static int CoinSort(int n,ref int count)
        {
            count++;
            int min;
            if (n < 3)
            {
                min = n;
            }
            else
            {
                min = CoinSort(n - 1, ref count) + 1;//先取一枚1元的硬币,需要的硬币数
                int min3 = CoinSort(n - 3, ref count) + 1;//先取一枚3元的硬币,需要的硬币数

                if (min > min3)
                {
                    min = min3;
                }
                if (n >= 5)
                {
                    int min5 = CoinSort(n - 5, ref count) + 1;
                    if (min > min5)
                    {
                        min = min5;
                    }
                }
            }

            return min;

        }
    }
}

这里写图片描述

很显然,这个效率是很低的。(代码不是最优)

下面再来看看采用递推的方式

C#代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BubbleSort
{
    class Program
    {
        static void Main(string[] args)
        {

            int[] coinVlue = new int[3] {1,3,5};
            CoinDp(11, coinVlue);
        }
        public static void CoinDp(int n, int[] coinValue)
        {
            int count = 0;
            int[] min = new int[n + 1];   //用来存储得到n块钱需要的硬币数的最小值
            min[0] = 0;
            for (int i = 1; i <= n; i++)
            {
                min[i] = int.MaxValue;//初始化数组中的每个值都是最大的整数
                for (int j = 0; j < coinValue.Length; j++)
                {
                    count++;
                    if (i >= coinValue[j] && min[i] > min[i - coinValue[j]] + 1)
                    {
                        min[i] = min[i - coinValue[j]] + 1;
                    }
                }

                Console.WriteLine("获取"+i+"块钱,最少需要的硬币数:"+min[i]+",执行的次数:"+count);
            }
            Console.ReadLine();
        }
    }
}

这里写图片描述
从运行结果可知,递推的方式解决硬币问题,效率更高。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值