动态规划是蓝桥杯常考的题型,同时也是建模常考的规划。但是我翻了一些博客,我发现很少有用Python实现。所以,参照几篇博客进行总结和归纳后,我整理出来了全面的动态规划使用场景+代码。
看一遍就理解:动态规划详解 - 云+社区 - 腾讯云 (tencent.com)
这位大佬写的真的通俗易懂,方便大家理解。文中涉及的代码转换成Python代码如下:
线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;
区域动规:石子合并,加分二叉树,统计单词个数,炮兵布阵等;
树形动规:贪吃的九头龙,二分查找书,聚会的欢乐,数字三角形等;
背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶等;
应用实例:最短路径问题,项目管理,网络流优化等。
青蛙跳阶-递归
def numWays(n):
if n==1:
return 1
elif n==2:
return 2
else:
return numWays(n-1)+numWays(n-2)
n=eval(input())
print(numWays(n)%1000000007)
青蛙跳阶-带备忘录的递归
lt=[1,2]
for i in range(2,n):
lt.append(lt[i-1]+lt[i-2])
n=eval(input())
print(lt[n-1]%1000000007)
青蛙跳阶-自底向上的动态规划
a,b=1,2
n=eval(input())
for i in range(2,n):
a,b=b,(a+b)%1000000007
print(b)
s=input()#输入格式x1,x2,x3,...
ls=list(map(int,s.split(',')))
n=len(ls)
dp=[1 for i in range(n)]
maxlen=1
for i in range(n):
for j in range(0,i):
if ls[i]>ls[j]:
dp[i]=max(dp[i],dp[j]+1)
maxlen=max(maxlen,dp[i])
print(maxlen)
print(dp)
结果: (和博客中分析结果一致)

分析:这道题看起来真的挺难的,但是如果正确分析,就会发现其实这道题的代码很简单。所以这个题的解决思路要重点关注。
题目和分析见这篇博客的[动态规划小试牛刀]
算法-动态规划 Dynamic Programming--从菜鸟到老鸟_HankingHu的博客-CSDN博客_动态规划
钢条切割-递归
value=[0,1,5,8,9,10,17,17,20,24,30]
length=list(range(0,11))#定义价格和长度
def cutmax(n):
if n<=0:
return 0
elif n==1:
return 1
else:
q=value[n]
for i in range(1,n):
q=max(q,cutmax(i)+cutmax(n-i))
return q
x=eval(input())
print(cutmax(x))
钢条切割-备忘录
这道题的备忘录方法没什么意思,备忘录方法无非是在递归的时候记录下已经调用过的子函数的值。过程:定义函数-->循环调用函数+保存结果,代码太长太冗余了,直接学习动态规划方法吧。
钢条切割-自底向上的动态规划
value=[0,1,5,8,9,10,17,17,20,24,30]
x=eval(input())
valuemax=value.copy()
if x>10:
valuemax+=[0]*(x-10)
for i in range(1,x+1):
for j in range(1,i):
valuemax[i]=max(valuemax[i],valuemax[j]+valuemax[i-j])
print(valuemax[x])
动态规划——合唱队 - Achilles_Heel - 博客园 (cnblogs.com)
这个博客也是用Python写的,我改进了一下。
问题补充:(我一开始的疑问)
问题分析中有这样的描述:(第i位同学被重复计算了一次),但是同样存在第i位同学不被重复计算的情况(如下图),这时-1就使合唱人数变小。但是我发现这时的升序人数+降序人数一定小于i取i-1或者i+1时:i=i+1时,升序=4,降序=3;i=i时,升序=3,降序=3。所以虽然当等于i时计算结果有误,但是不会影响最大值的选取。

在3.穷举分析的代码基础上写代码(对照答案结果一样)
s=input()#输入格式x1,x2,x3,...
ls=list(map(int,s.split(',')))
n=len(ls)
up=[1 for i in range(n)]
down=[1 for i in range(n)]
for i in range(n):
for j in range(0,i):
if ls[i]>ls[j]:
up[i]=max(up[i],up[j]+1)
if ls[n-i-1]>ls[n-j-1]:
down[n-i-1]=max(down[n-i-1],down[n-j-1]+1)
maxlen=[]
for k in range(n):
maxlen.append(n-(up[k]+down[k])+1)
print(min(maxlen))
print(up)
print(down)
print(maxlen)
动态规划之合并石子_Zekary的博客-CSDN博客_石子合并问题c语言
解法非常清晰,代码转成Python代码如下。
目标方程:minCost [ i ] [ i + k - 1] = min(minCost[ i ][ j ] + minCost[j + 1][ i + k - 1] + theCost)来源【算法笔记】区域型动态规划_石子并归_小宋今天要早睡的博客-CSDN博客_区域动态规划
s=input() #输入格式x1,x2,x3,...
ls=list(map(int,s.split(',')))
n=len(ls)
summ=[]
for i in range(n):
t=[]
for j in range(n):
if j<i:
t.append(0)
elif j==i:
t.append(ls[i])
else:
t.append(t[j-1]+ls[j])
summ.append(t)
dp=[[0 for i in range(n)] for j in range(n)]
for i in range(n):
if i<n-1:
dp[i][i+1]=ls[i]+ls[i+1]
for t in range(2,n+1):
for i in range(n-t):
a=dp[i][i+t-1]+summ[i][i+t]
b=dp[i+1][i+t]+summ[i][i+t]
for j in range(1,t-1):
b=min(b,dp[i][i+j]+dp[i+j+1][i+t]+summ[i][i+t])
dp[i][t+i]=min(a,b)
print(dp[0][n-1])
自从计算机二级开始我就对二叉树充满畏惧感,一开始碰到这道题也是完全不想看的状态,但是这种题还挺多的,之前碰到什么左孩子右兄弟也是完全不会做。。。所以这道题我要克服恐惧!
这篇博客就是我的学习内容,内容很清晰,而且排版令人很舒服。
def p(L,r):
if L>r:
return
print(root[L][r],end=' ')
if L==r:
return
p(L,root[L][r]-1)
p(root[L][r]+1,r) #输出根节点函数
n=eval(input())
s=input()
a=[0]+list(map(int,s.split()))
dp=[[0 for i in range(n+1)] for j in range(n+1)] #用来保存节点的得分
root=[[0 for i in range(n+1)] for j in range(n+1)] #用来保存i,j的共同的根节点
for i in range(1,n+1):
dp[i][i]=a[i]
dp[i][i-1]=1
root[i][i]=i #构造初始的数据
for len in range(1,n):
for L in range(1,n-len+1):
r=L+len
dp[L][r]=dp[L+1][r]+a[L]
root[L][r]=L
#print('len,L,r=',len,L,r)
for k in range(L+1,r):
if dp[L][r]<dp[L][k-1]*dp[k+1][r]+a[k]:
dp[L][r]=dp[L][k-1]*dp[k+1][r]+a[k] #取最大得分
root[L][r]=k
print(dp[1][n])
p(1,n)
结果:

从图中可以看出来计算分数一步一步的过程,结果相同。代码在题库中测试,百分百通过。
【这里看起来比较难,待补充】【最近要期中考试了,之后再补】
01背包问题详解(浅显易懂)_Iseno_V的博客-CSDN博客_01背包问题详解
背包问题的小试牛刀,这个比较容易,讲的也很详细,懂了这个之后复杂的背包问题就比较容易懂了。
n=eval(input())
V=eval(input())
s1=input() #w1,w2,w3,...
w=[0]+list(map(int,s1.split(',')))
s2=input() #v1,v2,v3,...
v=[0]+list(map(int,s2.split(',')))
f=[0 for i in range(V+1)]
for i in range(1,n+1):
for j in range(V,w[i]-1,-1):
f[j]=max(f[j],f[j-w[i]]+v[i])
print(f[V])
这个比较完整,讲解也比较详细易懂,也比较长,但是没有题目和代码。
背包九讲----整理+例题_smiling~的博客-CSDN博客_背包九讲
这个讲解不那么详细,但是最重要的dp方程都给出来了。如果前面的代码都跟着我一起学习过一遍了,思路也不需要讲的那么详细其实也可以明白了。所以这个也推荐看,但是代码是C++,后续陆续补充其中代码。【两个博客可以对照学习,代码可以来参照我的代码】
我直接用acwing的题库测试代码,通过的代码会放在这里。
注意一下,acwing网站里的Python编译器是Python2.x版本的,所以有些地方会莫名其妙报错,所以有些函数要稍微改一下。比如:input-->raw_input
n,V=map(int,raw_input().split(' '))
w=[0];v=[0]
for i in range(n):
t1,t2=map(int,raw_input().split(' '))
w.append(t1)
v.append(t2)
f=[0 for i in range(V+1)]
for i in range(1,n+1):
for j in range(V,w[i]-1,-1):
f[j]=max(f[j],f[j-w[i]]+v[i])
#print('i=',i,'\t','f=',f)
print(f[V])
输出一下结果可以清晰的看到往背包里加入物品的过程。
n,V=map(int,raw_input().split())
w=[0];v=[0]
for i in range(n):
t1,t2=map(int,raw_input().split())
w.append(t1)
v.append(t2)
f=[0 for i in range(V+1)]
for i in range(1,n+1):
for j in range(w[i],V+1):
f[j]=max(f[j],f[j-w[i]]+v[i])
#print('i=',i,'\t','f=',f)
print(f[V])
【先写到这,待补充】
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p