动态规划の入门小题,适合0基础看

动态规划是一种作者认为比较牛逼的算法,原因是作者初学时非常困难,认为这玩意非常抽象,它往往在求一些最大,最小XXXX问题上有妙用,这篇文章可以帮大家简单理解一下DP的含义。

对了,这玩意也叫DP,原因是动态规划的英文原意是(dynamic programming)。

然后我们以一个引子来介绍一下

大家可以先独立思考一下这道题目。

题目描述

今有面值为 1、5、11 元的硬币各无限枚。

想要凑出 n 元,问需要的最少硬币数量。

输入格式

仅一行,一个正整数 n。

输出格式

仅一行,一个正整数,表示最少需要的硬币个数。

样例:

输入#1:15

输出#1:3

输入#2:12

输出#2:2

这里附上交题链接:https://www.luogu.com.cn/problem/B3635

———————————————————————————————————————————

这个问题第一眼看到,我觉得大家的做法都是会想到贪心,先拿大的凑,然后再拿小的凑,然后多试几下之后就发现似乎不太对,比如20的话用贪心思路是11+5+1+1+1+1,而实际上5+5+5+5更优。

然后搞半天发现这玩意似乎没啥规律,咋拿都没有一个通用的最优策略,那咋办呢?

别急,我们先细想一下如何凑成某种面值?

假设现在我们要凑一个20,那么我这个20能怎么来呢? 可以轻松得出,从9加个11而来,从15加个5而来,从19加个1而来。

然后我再看9,15,19能咋来,然后再看能到9,15,19的数又是咋来的。。。。子子孙孙无穷尽也。。。。。。

这样想似乎思维难度有些大,不如我们正过来想。

一开始我一分钱没凑,于是我的初始状态就是0。

我们开一个表来方便理解

那我们现在拥有0的状态了,我们可以推一下从0到其他价值。

容易得到,0能去1,5,和11。

于是这个表变成了

然后我们0弄好了,再瞅瞅1能去哪

然后就发现我们能用1再+1变成2,1再+5变成6,1再+11变成12。

再看2能去哪

然后看3

再看4

然后发现4可以+1后到5,但是0可以直接+5到5,我用4到5的话要花费5个硬币,而我0到5只花费1个硬币,用4到5的话不是血亏吗,所以5应该留下那个更小的值,于是表就变成了

从这里开始发现,从前往后看的每个数,都是由前面的数倾尽全力给你的最小的硬币数量,是最优的,那就由此得出猜想,我后面的最优都可以通过前面的最优来算出来,我们继续进行模拟。

5:

6:

6到11发现也是血亏的,不如直接0到11,所以此时价值11最少只需1个币。

7:

8:

9:

10:

这里我们用10更新时发现15这里最优硬币数是5,但我自己凑(10)的硬币数最少只要俩,那我到15只用再加个5块的硬币就够了,于是15应该被优化成3枚硬币。。。。

然后同时我10+11超过20了,后面都是无效更新,那我就不填到表里去了。

后面一直用这个思路:

最后得出这个表

然后发现推20的话,最优是4枚硬币。

推所有的数都是这样,这个表里凑成的所有的价值,都是最优的。。

附上这题的AC代码:

可以用数组模拟这个表格,进行DP。

#include<bits/stdc++.h>

using namespace std;

const int N=1e6+5;
int a[N];

int main()
{
    int n; cin>>n;

    for(int i=1;i<=n;i++)
    {
        if(i<5) a[i]=a[i-1]+1;

        else if(i>=5 && i<11) a[i]=min (a[i-5]+1 , a[i-1]+1);

        else a[i]=min ( a[i-11]+1, min( a[i-5]+1 , a[i-1]+1 ));
    }

    cout<<a[n]<<" ";
}

最后总结一下,我们发现DP的思想,就是用前面的最优解来推后面的最优解,也就是局部最优可以推出全局最优,这也是这个思想抽象的地方,把这题理解透彻后明天听课应该能舒服一些,做完后可以用这种思路做一下其他简单DP题嗷,以便加深理解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值