算法设计练习题——动态规划

本文深入探讨了动态规划在解决各类复杂问题中的应用,包括斐波那契数列、数字三角形、图书分配、木棒分割等典型问题的算法设计与时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 1.满足递归式F(n)=F(n-1)+F(n-2)和初始值F(0)=F(1)=1的数列称为斐波那契数列。考虑如何计算该数列的第n项F(n)。(1)说明根据递归式直接完成计算,将有子问题重复求解;(2)说明该问题具有优化子结构;(3)写出求解F(n)的动态规划算法,并分析算法的时间复杂性。
(1)n为5时,要计算
		F(4),F(3);
		F(3),F(2);F(2),F(1)
		F(2),F(1)。
		重复计算
(2)优化子结构为:如果F(n)为第n项的斐波那契数,则F(n-1),F(n-2)分别应该为n-1项,n-2项斐波那契数。
(3)一维数组
F(n)=F(n-1)+F(n-2),
F(0)=F(1)=1,填表
  • 2.数字三角形问题:设有一个三角形的数塔,顶点为根结点,每个结点有一个整数值。从顶点出发,可以向左走或向右走,如图所示:
    在这里插入图片描述
    要求从根结点开始,请找出一条路径,使路径之和最大,只要输出路径的和。
    要求:(1) 写出递推方程;(2)写出算法伪代码;(3) 分析算法的时间复杂度。
(1)设P【i】为从顶点到第i个点的最长路径
则递归方程如下:
P【1】=T1
P【2】=P[1]+T2
P【4】=P[2]+T4
P【7】=P[4]+T7
P【11】=P[7]+T11
同理P【3,6,10,15】也能求出
其他:
P【i】=MAX(P【i-l】,P【i-l+1】)其中l是所在层数
(2)MAXPath(T[1;n],h)
P[1]=T1
a=1,b=1;
for i =1 to h-1 do
	P[a+i]=Ta+P[a]
	P[b+i+1]=Tb+P[b]
	a=a+i;
	b=b+i+1
for i =5 to n do
	if(P[I]==0) then
		P[i]=MAX(P[i-1],P[i-l+1])
reutrn MAX(P[n-l+1:n])
(3)算法时间复杂度:
O(n)
  • 3、在这里插入图片描述 算法:
    m[i,j] 为最小化的
    在这里插入图片描述
    且Si的并为{xi.xi+1,…xj-1,xj}
    则递归式
    m[i,j]=min{(m[i,k]+m[k+1,j]) i<=k<j,(xj-xi)2)
    m[i,i]=0

  • 4、假设书架上一共有9本书,每本书各有一定的页数,分配3个人来进行阅读。为了便于管理,分配时,各书要求保持连续,比如第1、2、3本书分配给第1人,4、5分配给第二人,6,7,8,9分配给第3人,但不能1,4,2分配给第1人,3,5,6分配给第2人。即用两个隔板插入8个空隙中将9本书分成3部分,书不能换位。同时,分配时必须整本分配,同一本书不能拆成两部分分给两个人。为了公平起见,需要将工作量最大的那一部分最小化,请设计一个动态规划算法。用s1,…,sn表示各本书的页数。
    (1)简明的写出问题的递推方程;
    (2)描述算法伪代码;
    (3)分析算法的时间复杂度。
    (不会,求解)

  • 5、将一根木棒折成若干份,每折一次的代价是当前这段木棒的长度, 总代价是折这根木棒直到满足要求所需要的所有操作的代价。例如,将一根长度为10的木棒折成四段,长度分别为2, 2, 3, 3,如果先折成长度为2和8的两段,再将长度为8的折成长度为2和6的两段,最后将长度为6的折成长度为3的两段,这些操作的代价是10+8+6=24;如果先折成长度为4和6的两段,在分别将长度为4的折成长度为2的两段、长度为6的折成长度为3的两段,则这些操作的代价是10+4+6=20,比上一种方案更好一些。该问题的输入是木棒的长度L和一些整数c1,…,cn, 要求将木棒折成长度为c1, …, cn的n段且操作代价最小,请设计动态规划算法解决该问题。

    m[i,j]是将i~j段连成整段时折成两份的最小代价
    m[i,j]=min(m[i,k]+m[k+1,j],k<=i<j)+ci+....+cj
    m[i,i]=0
    
  • 3.考虑三个字符串X,Y,Z 的最长公共子序列LCS(X,Y,Z)。
    (1)寻找反例X,Y,Z 使得LCS(X,Y,Z)≠LCS(X, LCS(Y,Z));
    (2)设计动态规划算法计算X,Y,Z 的最长公共子序列,分析算法的时间复杂度。
    Y=abc,Z=cab,X=c
    LCS(X,Y,Z) = c
    LCS(X, LCS(Y,Z)) = null
    递归方程:
    c【i,j,k】为XiYjZk的最长公共子序列的长度
    C【i,j,k】=0,i 或j或k=0
    C[i,j,k]=C[i-1,k-1,j-1]+1,xi=yj=zk
    C[i,j,k]=max{C[i-1,j,k],C[i,j-1,k],C[i,j,k-1],C[i-1,j-1,k],C[i,j-1,k-1],C[i-1,j,k-1]}
    算法时间复杂度O(n3

  • 4
    在这里插入图片描述
    (1)直接按照bi进行贪心:
    a) 第一次找l1。
    b) 第二次时,找到最小的i,满足ai>=b1。
    c) 然后每次找最靠前的与当前所选区间不重叠的区间即可
    (2)maxp【i】为以Ii为起始区间的最大数量互不相交区间的权重之和,时间复杂度为O(N)
    m[i]为Ii,…In这些区间的P2问题的解
    m[n]=vn
    m[i]=max(m[i+1],maxp[i])

    伪代码:
    m[n]=vn
    for i = n-1 to 1 do
    	m[i]=max(m[i+1],maxp[i])
    return m[1]
    
  • 5、T1和T2是两棵有序树,其中每个结点都有一个标签,考虑树上的三种操作,删除一个子树、插入一个子树和更改一个结点的标签,请设计一个算法,求得从T1变化到T2所需要的最少操作数,要求写出递推方程,程序伪代码并分析时间复杂性。
    (未解决求解)

  • 6、正整数n 可以拆分成若干个正整数之和,考虑拆分方案的个数。
    (1) 令g(i,j)表示拆分整数i时最大加数不超过j的方案个数, 证明:g(i,j)=g(i,j-1)+g(i-j,j)。
    (2)根据(1)设计动态规划算法计算整数n的拆分方案个数,要求算法的时间复杂度为O(n2)

    (1)g(i,j-1)为将i拆分为最大加数不超过j-1的方案数,g(i-j,j)为将i-j拆分为最大加数不超过j的方案数,即将i拆分为最大加数为j的方案数,因此,g(i,j)=g(i,j-1)+g(i-j,j)
    (2)递归方程:g(i,i)=1
    	g(i,j)=g(i,j-1)+g(i-j,j)
    	伪代码:
    	for i=1 to n
    		g(i,1)=1
    		g(1,i)=1
    		g(0,i)=1
    	for i = 2 to n do
    		for j =  2 to i do
    			g(i,j)=g(i,j-1)+g(i-j,j)
    	return g(n,n)
    
    • 7.乌龟棋:乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。
      在这里插入图片描述
      乌龟棋中M张爬行卡片,分成4种不同的类型(M张卡片中不一定包含所有4种类型 的卡片,见样例),每种类型的卡片上分别标有1、2、3、4四个数字之一,表示使用这种卡 片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择 一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。 游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到 该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同。现已知棋盘上每个格子的分数和所有的爬行卡片,求得一种卡片使用顺序使得最终游戏得分最多。
      例:有9个格子上的分数分别为6 10 14 2 8 8 18 5 17,有卡片1 1 1 2 3,则使用爬行卡片顺序为1,1,3,1,2,得到的分数为6+10+14+8+18+17=73。注意,由于起点是11,所以自动获得第11格的分数6。
      递归方程:
      s [ i ] [ j ] [ k ] [ l ] s[i][j][k][l] s[i][j][k][l]为使用了i张1,j张2,k张3,l张4时所得的最大分数,且此时位置为i+2j+3k+4*l
      s [ 1 ] [ 0 ] [ 0 ] [ 0 ] = v 1 s[1][0][0][0]=v_1 s[1][0][0][0]=v1
      s [ 0 ] [ 1 ] [ 0 ] [ 0 ] = v 2 s[0][1][0][0]=v_2 s[0][1][0][0]=v2
      s [ 0 ] [ 0 ] [ 1 ] [ 0 ] = v 3 s[0][0][1][0]=v_3 s[0][0][1][0]=v3
      s [ 0 ] [ 0 ] [ 0 ] [ 1 ] = v 4 s[0][0][0][1]=v_4 s[0][0][0][1]=v4
      s [ i ] [ j ] [ k ] [ l ] = m a x ( s [ i − 1 ] [ j ] [ k ] [ l ] , s [ i ] [ j − 1 ] [ k ] [ l ] , s [ i ] [ j ] [ k − 1 ] [ l ] , s [ i ] [ j ] [ k ] [ l − 1 ] ) + v ( i + 2 j + 3 k + 4 l ) s[i][j][k][l] = max(s[i-1][j][k][l],s[i][j-1][k][l],s[i][j][k-1][l],s[i][j][k][l-1])+v_{(i+2j+3k+4l)} s[i][j][k][l]=max(s[i1][j][k][l],s[i][j1][k][l],s[i][j][k1][l],s[i][j][k][l1])+v(i+2j+3k+4l)
  • 8、输入数组A[0:n]和正实数d,试设计一个动态规划算法输出A[0:n]的一个最长子序列,使得子序列中相继元素之差的绝对值不超过d。分析算法的时间复杂度。
    设l[i]为a0,,,,,ai的包含ai的满足条件的最长子序列的长度。

    l[0]=1
    l[i]=max(l[j],0<=j<=i-1且|aj-ai|<=d)+1

    伪代码:
    l[0]=1
    for i =2 to n do
    	l[i]=0
    	for j = 0 to i-1 do 
    		if l[j]>l[i] and abs(aj-ai)<=d then
    			l[i]=l[j]
    			s[i]=j
    	l[i]=l[i]+1
    return l,s
    O(n^2)
    
    • 9、输入凸n边形p1,p2,…pn,其中顶点按凸多边形边界的逆时针序给出,多边形中不相邻顶点间的连线称为弦。试设计一个动态规划算法,将凸边形p1,p2,…pn 剖分成一些无公共区域的三角形,使得所有三角形的周长之和最小。
    递归方程:
    设c[i,j]为将pi,....pj顶点划分后的最小周长
    则c[i,i+1]=v(i,i+1)
    c[i,i+2]=v[i,i+1]+v[i+1,i+2]+v[i,i+2]
    c[i,i]=0
    c[i,j] = min(c[i,k]+c[k,j],i<=k<=j)+v(i,j)
    伪代码:
    for i =1 to n do
    	c[i,i]=0
    	c[i,i+1]=v[i,i+1]
    	c[i,i+2]=v[i,i+1]+v[i+1,i+2]+v[i,i+2]
    for i =1 to n do
    	for j = i+3 to n do
    		c[i,j]=+∞
    		for k = i to j do
    			if c[i,k]+c[k,j] < c[i,j] then
    				c[i,j]=c[i,k]+c[k,j] 
    				break[i,j]=k
    		c[i,j]=c[i,j]+v[i,j]
    return c,break
    
    
  • 10、输入一棵加权树T,其中每条边的权值均是实数,试设计一个动态规划算法输出权值最大的子树。
    设m[pi]为以节点pi为根的树的最大权值
    则m[pi]=0,pi为叶节点
    m[pi]=max(m[pil]+v[pi,pil],m[pir]+v[pi,pir])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值