目录
一、为什么要讲动态规划
0.我的朴素情感
作为一名数学和代码爱好者,我很荣幸能够用动态规划作为我在csdn上的处女篇,很早之前就想分享一些有趣有好玩的内容给各位广大网友,碍于懒癌,不知从何说起等一些缘由,迟迟不能发。其实,不用考虑过多,大胆分享就好了!
1.简要说明理由
动态规划的算法问题,网站上有大量参考答案,但我跟他们的不太一样,我是真正会通过数学的抽象思维深入解答每一个问题中,有时候我为了寻找多解和方法通过会专研2到3小时。就是专研寻找解题的方法和锻炼自己的抽象思维和逻辑推导。相比别人的直接暴力求解和只给出冰冷的代码,我的讲解可能会更加适合新手以及想继续加强自己的数学思维的网友们。
二、用数学思维结合编程语言解决问题
1.动态规划的解题思想概述
动态规划核心就是函数递归思想,而函数递归思想,主要表达抽象思维,计算机语言魅力在于,给定了计算路径或者规则,输入和输出就交给晶体管解决了。言归正传哈,不妨设 f(m,n) 为分法总数,接下来就是要给定计算路径了,注意这里的计算路径类似数列递推公式,给出首几项的值,求第n项递推公式,但是计算机不要求具体的计算公式,因为计算机它可以自行迭代啊!故最简单的方法,就是通过找出第n项的前几项式子,看看它们和通项式子的关系式(也就是可迭代路径)。
2.开胃菜一
言归正传,友友们!今天这篇先拿出两道小题来开开胃。分别是HJ的61和91
首先这是HJ61(放苹果_牛客题霸_牛客网 (nowcoder.com) ),涉及组合数学,抽象代数和一点点概率的数学问题。
3.菜一吃法
所有动态规划,建议先分析,本题观察规律如下:
双变量,显然,m, n 都递归,先考虑初始项,m =0, n=1 (题目条件),无论是无苹果还是一个盘子,都只有一种放法,即 f(0,n) = f(m ,1) =1 (注意 f(0,1) 只是特殊条件。
先看变量n(较简单),不妨设 m < n, 盘多果少,此时,可用盘子为m,由于盘子一致,所以,f(n,m) =f(m,m)。
再看m变量递归, 不妨设m >=n, 即确保盘子不空着,设每个盘子至少一个苹果,则放法数为f(m-n,n)。注意,f(m,n)= f(不空盘子法子)+f(空盘子法子),f(不空盘子法子)=f(先每个盘子放一个* 剩下苹果再放)= 1 * f(m-n,n) ,简单解释下f(不空)怎么来的,事件状态A = 状态(A1 + A2),熵增量(A) = 熵增量(A1 * A2) 。(公式待定商榷,为了便于大家理解)
最后看f(空盘子),比上面好理解,即至少存在一个空盘子,则f(空)=f(m,n-1) 。
推到完毕,以下是py,注意代码需要一些Python基础,否则不好理解哦。
def f(m, n):
if m == 0 or n == 1: #初始条件
return 1
if m < n: #盘多果少时
return f(m, m) #递推
else:
return (f(m, n-1) + f(m-n, n)) #递推
while True: #运行
try:
m, n = map(int,input().split())
print(f(m,n))
except:
break
如果你已学会亿点点 请看下一题,并尝试做下,看下自己掌握了没有(下一题会比上一题简单哦)。
4.开胃菜二
题目是HJ91(走方格的方案数_牛客题霸_牛客网 (nowcoder.com))
5.菜二吃法
分析:老套路,函数递归思想,重要的条件不能走回头路,决定了我们递归的基础,从左上到右下,是个路线规划问题。 不妨设走法为f(n,m),显然,f(n,m) = f(n-1,m) + f(n,m-1) , 即往右走一步还有多少种+往下走一步还有多少种,递推法。建议花格子自己揣摩下,更方便理解哦。
有个小陷阱需要注意下:由于棋盘格子数不能为0,题目给出的是正整数条件,但按照上面地推法,必定会导致出现n=0或m=0的情况,比如输入f(1,1) = f(0,1) + f(1,0) ,但我们从物理角度上看,格子数为零,还有存在空间么,这可能是题目设置不太好。别担心,物理角度不好理解,我们从数学角度上看,令n 或者 m 恒为1,显然我们知道f(1,1) = 2,f(1,m)=m+1,f(n,1)=n+1,由此可以推出f(0,1) = f(1,0) = 1(建议也是画下格子,简单推下就好了)。其实,将m,n看成坐标点是更为准确的说法,即将m,n看做笛卡尔坐标系中一个动点,求其到原点的行动路线有几条,其它条件与题目一致,此时,从物理角度来看,m和n就是线不再是格子了,题目也更严谨些。题目设置问题,不过总体来说问题不大。
以下是Python代码,
while 1:
try:
n,m = map(int,input().split())
def f(n,m): #不妨设走法为f
if n == 0 or m == 0: #初始条件,(0,0)无意义,但n>=1,使得解题严谨
return 1
else:
return (f(n-1,m) + f(n,m-1)) #递归通项
print(f(n,m))
except:
break
三、总结感谢
希望此篇可以帮助你更好的加强和训练自己数学思想,以方便借助强大的计算机来解决生活遇到的一些问题,当然即使做不到,但可以训练自己数学思想还是有好处的。
如果看下来觉得本篇还不错请你不妨给我点点赞,如果能关注和收藏最好不过了!你的支持和鼓励是我创作的源泉!最后,谢谢广大网友的观看(即便推送量不佳,还是谢谢你们观看呀)!