什么影响了你理解动态规划(一)
什么影响了你理解动态规划(一)
1. 简介动态规划
几乎很难给动态规划下一个易于理解的定义,映入眼帘的只有动态二字,将动态与其定义作一个贴切的解释就是多阶段决策。最后的结果与每个阶段的决策有关,其动态的概念在于最后的结果与每一个阶段的决策有关。这样一来将动态规划与贪心算法作比较就可以发现,动态规划属于全局最优算法,贪心算法属于局部最优算法。在了解动态规划的第一步只要知道其两个特点即可:多阶段与决策。
2. 动态规划问题的完整建模过程
(1)将问题过程划分成恰当的阶段;
(2)正确选择状态变量 S k S_k Sk,使它即能描述过程的演变,又要满足无后效性;
(3)确定决策变量 u k u_k uk及每阶段的允许决策的集合 D k ( S k ) D_k(S_k) Dk(Sk);
(4)正确写出状态转移方程;
在实际解题过程中,人们往往将重心放在第(2)和第(4)上。因为大多数情况下,很难确定将问题分为多少个阶段,要么阶段在题目表示中已经暗示,要么这个阶段数是动态的。而第(3)步也同样重要,因为每一个阶段都要在决策集中选择一个决策才能到达下一个阶段。
3. 什么影响了你理解动态规划
网上部分文章喜欢举斐波那契数列的例子来向初学者说明动态规划的内涵。但不幸的是,这个例子的建模过程缺少了其中的某些步骤,会导致读者在理解上出现偏差。在此说明斐波那契数列的例子在哪些步骤会缺省。
斐波那契数列的递推定义为: F ( 1 ) = 1 , F ( 2 ) = 1 , F ( n ) = F ( n − 1 ) + F ( n − 2 ) ( n ≥ 3 ) F(1)=1,F(2)=1,F(n)=F(n-1)+F(n-2) (nge3) F(1)=1,F(2)=1,F(n)=F(n−1)+F(n−2)(n≥3)。之所以很多人喜欢用这个例子是因为,它天然地给出了递推式与状态表示,让人轻而易举的写出程序。还可以举出递归做法与动态规划做法的一些比较。但这并不足以帮助读者理解什么是动态规划,只是徒增了无畏的成就感罢了。
假设要求斐波那契数列的第100个数,则题目天然的将建模过程分成了100个阶段,每个阶段依赖它前面的两个数( f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n)=f(n-1)+f(n-2) f(n)=f(n−1)+f(n−2))。同样很自然地,用数组变量f[i]代表第i个数完成了状态表示。但是它唯独缺少了第(3)步,每一个阶段并没有决策集或者说它的每一个阶段有且仅有唯一的一个决策(就是依赖它前面的两个数)。这个例子的第(3)步骤不够明显,导致许多读者并无法通过这个例子去理解动态规划的决策集,他只记得了这个例子,并不会记得动态规划。
4. 举一个可以让你理解动态规划建模四个步骤的例子
4.1 找零题目描述
Z国的货币系统包含面值1元、4元、16元、64元共计4种硬币,以及面值1024元的纸币。现在小Y使用1024元的纸币购买了一件价值为 N ( 0 < N ≤ 1024 ) N (0 < N le 1024) N(0<N≤1024)的商品,请问最少他会收到多少硬币?
输入描述:
一行,包含一个数N。 1
输出描述:
一行,包含一个数,表示最少收到的硬币数。 1
示例1
输入
200 1
输出
17 1
说明
花200,需要找零824块,找12个64元硬币,3个16元硬币,2个4元硬币即可。 1
决策集
可能一看题目,给人最直观的感觉就是决策集,可以将当前找零的n元的纸币先换成 1元 或 4元 或 16元 或 64元的一枚硬币,然后剩下 n-1元 或 n-4元 或 n-16元 或 n-64元的纸币,则进入了下一个阶段,下一个阶段也同样是在这个决策集中选择。其中的分法就是组成了决策集,需要读者慢慢体会一下。
阶段与状态表示
这道题目的状态表示也非常简单,可以使用数组 f[n]来表示 n元纸币的最小组成硬币数。其实这个天然已经帮助我们确定了计算的阶段数。
状态转移方程
在给出状态转移方程前,先考虑这样一个例子。求100元纸币的最小组成硬币数。
所以状态转移方程就是:
f ( n ) = m i n f ( n − 1 ) + 1 , f ( n − 4 ) + 1 , f ( n − 16 ) + 1 , f ( n − 64 ) + 1 f(n)=min{f(n-1)+1,f(n-4)+1,f(n-16)+1,f(n-64)+1} f(n)=minf(n−1)+1,f(n−4)+1,f(n−16)+1,f(n−64)+1
每一个 f ( n ) f(n) f(n)均代表一个阶段,由状态转移方程可以得到,当前阶段需要依赖之前的阶段,由此可得出计算顺序为 n从小到大开始计算。
public static int func(int N){ int[] coins = {1,4,16,64}; int n=1024-N; int[] f= new int[n+1]; f[0]=0; for(int j=1;j<=n;j++){ // 分为 n 个阶段,按照状态转移方程 n 从小到大进行计算 f[j]=Integer.MAX_VALUE; for(int i=0;i<coins.length;i++){ // 每一个阶段都要在决策集中进行决策,coins 即为决策集 if(j>=coins[i]){ f[j]=Math.min(f[j],1+f[j-coins[i]]); } } } return f[n]; } 123456789101112131415 4.2 01背包问题
题目描述
在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]。
例子样例 1:输入: [3,4,8,5], backpack size=10输出: 9 样例 2:输入: [2,3,5,7], backpack size=12输出: 12 1234567
确定阶段
题目其实已经暗示了阶段数,即在遍历到第 i 个物品时,即处于第 i 个阶段,共有 n 个物品,即会有 n 个阶段。
决策集
决策集其实就只有两种,即放入背包,不放入背包。
状态表示
对于背包问题而言,我们的状态即要表示当前处于第几个阶段,又要表示对当前物品做出决策后记录背包的重量。
使用 f[i][w]来表示在第 i阶段时,对第 i个物品作出决策(放入与不放入)后,背包能否达到 w重量(true / false)。
状态转移方程
设f[i][w]表示能否用前 i个物品拼出重量 w重量(true/false)。
代码:
public int backPack(int m, int[] A) { int n=A.length; if(n==0) return 0; boolean[][] f=new boolean[n+1][m+1]; f[0][0]=true; for(int i=1;i<=n;i++){ // 分成 n 个阶段,每个阶段选择一个物品 for(int j=0;j<=m;j++){ f[i][j]=f[i-1][j]; // 对第i个物品做出不放入的决策 if(j-A[i-1]>=0&&f[i-1][j-A[i-1]]){ // 对第i个物品做出放入的决策 f[i][j]=true; } } } int res=0; for(int i=m;i>=0;i--){ if(f[n][i]){ res=i; break; } } return res; }
1234567891011121314151617181920212223总结
这两个例子尽管类型不同,但可以让初学者完成对动态规划问题特点的认识。后续还会继续完成动态规划这一专题的总结与归纳,包括动态规划问题的分类与深入等。希望本文对你了解动态规划有所帮助,若有帮助,可以点个赞,若有疑问可以评论。关注公众号“NullPointerException”可以同步查看内容。
相关知识
气候的改变影响了什么
动态规划 摆花 题解
这10种外国树,深度影响了我国的园林绿化
什么是景观生态学及其原理
静态页面和动态页面中的静态和动态到底指的是什么
探讨城镇园林植物该如何规划和应用
小心“花”影响了你的运气
摆花 (DP动态规划)
算法(七)100个经典的动态规划方程
【动态规划】摆花
网址: 什么影响了你理解动态规划(一) https://www.huajiangbk.com/newsview1250740.html
上一篇: 各类型青菜卷筒青 |
下一篇: YVES SAINT LAURE |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039