算法设计与分析2023秋-头歌实验-实验七 动态规划

news2024/12/22 23:55:44

文章目录

  • 第1关:数塔问题
    • 任务描述
    • 相关知识
    • 编程要求
    • 解题思路
    • 测试说明
    • 参考答案
  • 第2关:最长公共子序列
    • 任务描述
    • 相关知识
    • 编程要求
    • 解题思路:
    • 测试说明
    • 参考答案
  • 第3关:求序列-2 11 -4 13 -5 -2的最大子段和
    • 任务描述
    • 相关知识
    • 编程要求
    • 解题思路:
    • 测试说明
    • 参考答案
  • 第4关:求最长的单调递增子序列长度
    • 任务描述
    • 相关知识
    • 编程要求
    • 解题思路:
    • 测试说明
    • 参考答案
  • 第5关:矩阵连乘问题
    • 任务描述
    • 相关知识
    • 编程要求
    • 测试说明
    • 参考答案

第1关:数塔问题


任务描述

本关任务:编写用动态规划解决数塔问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

image.jpg
求上图从顶层到顶层的一个路径,使路径上的数字和最大。要求输出最大的数字和max和数值和最大的路径。

解题思路

原始信息有层数和数塔中的数据,层数用一个整型变量n存储,数塔中的数据用二维数组data,存储成如下的下三角阵:

             9
             12    15
             10    6     8
             2     18    9    5
             19    7     10   4   16

必需用二维数组d存储各阶段的决策结果。二维数组d的存储内容如下:、

  d[n][j]=data[n][j],         j=1,2,……,n;
    d[i][j]=max(d[i+1][j],d[i+1][j+1])+data[i][j],   i=n-1,n-2,……1,j=1,2,……,i   

最后d[1][1]存储的就是问题的结果。

测试说明

平台会对你编写的代码进行测试:
测试输入:

5
9
12    15
10    6     8
2    18     9    5
19    7     10   4   16

输出示例:

max=59
数值和最大的路径是:9->12->10->18->10

参考答案

#include <stdio.h> 
#define N 5 //问题规模
int main() {
    int a[50][50];
    a[1][1] = 9;
    a[2][1] = 12, a[2][2] = 15;
    a[3][1] = 10, a[3][2] = 6, a[3][3] = 8;
    a[4][1] = 2, a[4][2] = 18, a[4][3] = 9, a[4][4] = 5;
    a[5][1] = 19, a[5][2] = 7, a[5][3] = 10, a[5][4] = 4, a[5][5] = 16;

    int i, j, dp[50][50] = { 0 }, path[50][50] = { 0 };
    for (j = 1; j <= N; j++)                           //初始子问题 ,倒数第二层(第i-1层)开始
        dp[N][j] = a[N][j];
    for (i = N - 1; i >= 1; i--)                       //进行第 i+1 层的决策,从i 到 1 向上
        for (j = 1; j <= i+1; j++) {                     //每一层有 i+1 个
            if (dp[i + 1][j] > dp[i + 1][j + 1]) {
                dp[i][j] = a[i][j] + dp[i + 1][j];
                path[i][j] = j;                        //本次决策选择下标j的元素
            }
            else {
                dp[i][j] = a[i][j] + dp[i + 1][j + 1];
                path[i][j] = j + 1;                     //本次决策选择下标j+1的元素
            }
        }
    printf("max=%d\n", dp[1][1]);
    printf("数值和最大的路径是:");            
    j = path[1][1];                          //计算dp[1][1]的选择
    for (i = 1; i < N; i++)
    {
        printf("%d->", a[i][j]);
        j = path[i][j];                         //计算dp[i][j]的选择
    }
    printf("%d\n", a[i][j]);

}
/********** End **********/

第2关:最长公共子序列

任务描述

本关任务:编写用动态规划解决最长公共子序列问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

求字符串序列“ABCDBAB”和“BDCABA”的最长公共子序列

解题思路:

递推关系分析: 设 A=“a0,a1,…,am−1”,B=“b0,b1,…,bn−1”,Z=“z0,z1,…,zk−1” 为它们的最长公共子序列。 有以下结论: 1)如果am−1=bn−1,则zk−1=am−1=bn−1,且“z0,z1,…,zk−2”是“a0,a1,…,am−2”和“b0,b1,…,bn−2”的一个最长公共子序列; 2)如果am−1=bn−1,则若zk−1=am−1,蕴涵“z0,z1,…,zk−1”是“a0,a1,…,am−2”和“b0,b1,…,bn−1”的一个最长公共子序列; 3)如果am−1=bn−1,则若zk−1=bn−1,蕴涵“z0,z1,…,zk−1”是“a0,a1,…,am−1”和“b0,b1,…,bn−2”的一个最长公共子序列。 定义c[i][j]为序列“a0,a1,…,ai−1”和“b0,b1,…,bj−1”的最长公共子序列的长度,计算c[i][j]可递归地表述如下: 1)c[i][j]=0 如果i=0或j=0; 2)c[i][j]=c[i−1][j−1]+1 如果i,j>0,且a[i−1]=b[j−1]; 3)c[i][j]=max(c[i][j−1],c[i−1][j]) 如果i,j>0,且a[i−1]=b[j−1]。 由二维数组c的递归定义,c[i][j]的结果依赖于c[i−1][j−1],c[i−1][j]和c[i][j−1]。可以从c[m][n]开始,跟踪c[i][j]结果的产生过程,从而逆向构造出最长公共子序列。

测试说明

平台会对你编写的代码进行测试:
测试输入:

a=“ABCDBAB”
b=“BDCABA”

输出示例:

BCBA

参考答案

/*动态规划之最大子序列*/
#include <stdio.h>
int main()
{
	char A[7]={'A','B','C','B','D','A','B'};			
	char B[6]={'B','D','C','A','B','A'};
	int dp[8][7];						//dp数组记录最长公共子序列的长度 
	for(int i=0;i<7;i++)		//边界赋值为0 
	{
		dp[i][0]=0;
	 }
	for(int i=0;i<8;i++)
	{
		dp[0][i]=0;
	}
	
	// printf("test1=%d\n",dp[6][7]);
	
	for(int i=1;i<=7;i++)
	{
		for(int j=1;j<=6;j++)
		{
			if(A[i-1]==B[j-1])			//如果相等就dp[i][j]=dp[i-1][j-1]+1; 
			{
				dp[i][j]=dp[i-1][j-1]+1;
			}
			else{
					if(dp[i-1][j]>dp[i][j-1])
					{
						dp[i][j]=dp[i-1][j];   //取两者之间较大者;局部的最优值 
					}
					else{
						dp[i][j]=dp[i][j-1];
					} 	
			}
		}
	  }
	  
	char str[100];							//记录公共的字符
	int i=7,j=6;
	int count=0;
	while(i>0&&j>0)
	{
		if(dp[i][j]==dp[i-1][j])			//往上遍历 
		{
			i--;
		}
		else if(dp[i][j]==dp[i][j-1])		//往左遍历 
		{
			j--;
		}
		else{
			str[count++]=A[i-1];
			i--;
			j--;
		}
	}
	
	for(int i=count-1;i>=0;i--)
	{
		printf("%c",str[i]);
	 } 
 }

第3关:求序列-2 11 -4 13 -5 -2的最大子段和

任务描述

本关任务:编写用动态规划解决最大子段和问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

给定由n个整数(可能为负数)组成的序列:a1,a2,……,an, 求该序列的最大子段和。当所有整数均为负数,定义其最大子段和为0。

解题思路:

定义b[j]=max(a[i]+a[i+1]+…+a[j]),其中1<=i<=j,并且1<=j<=n。那么所求的最大子段和可以表示为max b[j],1<=j<=n。 由b[j]的定义可知,当b[j−1]>0时b[j]=b[j−1]+a[j],否则b[j]=a[j]。故b[j]的动态规划递归表达式为: b[j]=max(b[j−1]+a[j],a[j]),1<=j<=n。

测试说明

平台会对你编写的代码进行测试:
测试输入:

6
-2 11 -4 13 -5 -2

输出示例:

20

参考答案

#include <stdio.h>
/********** Begin **********/
int main(){
	int n;
	scanf("%d",&n);
	int a[n][2];
	int max=0;
	for(int i=0;i<n;i++){
		scanf("%d",&a[i][0]);
		if(i==0){
			a[i][1]=a[i][0];
		}
		else{
			a[i][1]=a[i-1][1]+a[i][0]>a[i][0]?a[i-1][1]+a[i][0]:a[i][0];
		}
		
		max=max>a[i][1]?max:a[i][1];
		
	}
	printf("%d",max);
	return 0;
	
}
/********** End **********/

第4关:求最长的单调递增子序列长度

任务描述

本关任务:编写用动态规划解决求最长的单调递增子序列长度问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

给定一个长度为n的数组,找出一个最长的单调递增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为7的数组A5,6,7,1,2,8,9,则其最长的单调递增子序列为5,6,7,8,9,长度为5。求318714101223411624的最长的单调递增子序列长度。

解题思路:

设长度为n的数组为(a[0],a[1],a[2],…,a[n−1]),则假定以a[j]结尾的数组序列的最长递增子序列长度为L(j),则L(j)=max(L(i))+1,i<j且a[i]<a[j]。也就是说,我们需要遍历在j之前的所有位置i(从0到j−1),找出满足条件a[i]<a[j]的L(i),求出max(L(i))+1即为L(j)的值。最后,我们遍历所有的L(j)(从0到n−1),找出最大值即为最大递增子序列。

测试说明

平台会对你编写的代码进行测试:
测试输入:

10
3 18 7 14 10 12 23 41 16 24

输出示例:

6

参考答案

#include <stdio.h>
/********** Begin **********/
int main(){
	 int n;
	 scanf("%d",&n);
	 int m[n][3];
	 m[0][1]=1;
	 m[0][2]=0;
	 for(int i=0;i<n;i++){
		scanf("%d",&m[i][0]);
		if(i!=0){
			m[i][1]=0;
			int k=i-1;
			while(k>=0){
				if(m[i][0]>m[k][0]){
						if(k==i-1){
							m[i][1]=m[k][1]+1;
							m[i][2]=k;
						}
						else{
							int max=m[k][1]+1;
							if(max>m[i][1]){
								m[i][1]=max;
								m[i][2]=k;	
							}
					    }
				}
			 k--;
			}
			if(k<0&&m[i][1]==0){
			    m[i][1]=1;
			    m[i][2]=i;
			}
		}
	 }
 
	int max=m[0][1],j=0;
	for(int i=0;i<n;i++){
	      if(m[i][1]>=max){
	             max=m[i][1];
	             j=i;
	      }
	 }
	printf("%d\n",max);
}
/********** End **********/

第5关:矩阵连乘问题

任务描述

本关任务:编写用动态规划解决矩阵连乘问题。

相关知识

为了完成本关任务,你需要掌握:动态规划。

编程要求

将矩阵连乘积AiAi+1…Aj简记为A[i:j],其中i<=j。设在矩阵Ak和Ak+1之间将矩阵链断开,则其相应加括号为(AiAi+1…Ak) (Ak+1Ak+2…Aj)。A[i:j]的计算量等于三部分计算量之和: (1)A[i:k]的计算量, (2)A[k+1:j]的计算量, (3)A[i:k]与A[k+1:j]相乘的计算量。 设计算A[i:j]所需最少乘积数目为,则原问题的最优值为。 当i=j时,a[i:j]=Ai,因此,m[i][j]=0,i=1,⋅⋅⋅,n 当i<j时,m[i][j]=i<k<jmin{m[i][k]+m[k+1][j]+pi−1pkpj} 其中,矩阵Ai的矩阵数为pi−1×pi 矩阵A1的维度:p0p1=3035 矩阵A2的维度:p1p2=3515 矩阵A3的维度:p2p3=155 矩阵A4的维度:p3p4=510 矩阵A5的维度:p4p5=1020 矩阵A6的维度:p5p6=2025 求这6个矩阵连乘的最小相乘次数。

测试说明

平台会对你编写的代码进行测试:
测试输入:

6
30 35
35 15
15 5
5 10
10 20
20 25

输出示例:

m[1][6]=15125

参考答案

#include <stdio.h>
#include <stdlib.h>
/********** Begin **********/
int main(){
	int n;
	scanf("%d",&n);
	int a[n][2];
	int b[n][n]={0};
	for(int i=0;i<n;i++){
	    scanf("%d %d",&a[i][0],&a[i][1]);   
	}
	
	for(int i=1;i<n;i++){
	    for(int j=0;j<n-i;j++){
	      b[j][j+i]=b[j][j]+b[j+1][j+i]+a[j][0]*a[j][1]*a[j+i][1];         
	      int k=j+1;
	      for(;k<j+i;k++){
	              int t=b[j][k]+b[k+1][j+i]+a[j][0]*a[k][1]*a[j+i][1];
	                if(t<b[j][j+i]) {
	                    b[j][j+i]=t;
	                }
	              
	      }
	
	    }
	        
	}
	printf("m[%d][%d]=%d",1,n,b[0][n-1]);
	return 0;
}
/********** End **********/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1322750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单位委托保管档案好处在哪里

单位委托保管档案可以享受专业的管理、节省空间、提高效率、保护保密性和安全性&#xff0c;以及保证档案的长期保存等好处&#xff0c;从而提升工作效率和档案管理的质量。 具体而言&#xff0c;委托档案寄存专久智能保管档案的好处有以下几点&#xff1a; 1. 专业管理&#x…

数据结构之<树>的介绍

树的基本概念 在数据结构中&#xff0c;树&#xff08;Tree&#xff09;是一种层次结构&#xff0c;由节点和边组成。树的基本概念包括根节点、子节点、父节点、兄弟节点等。节点拥有零个或多个子节点&#xff0c;除了根节点外&#xff0c;每个节点有且仅有一个父节点。树的层…

Leetcode—128.最长连续序列【中等】

2023每日刷题&#xff08;六十四&#xff09; Leetcode—128.最长连续序列 实现代码 class Solution { public:int longestConsecutive(vector<int>& nums) {unordered_set<int> s;for(auto num: nums) {s.insert(num);}int longestNum 0;for(auto num: s) …

鸿蒙与安卓的对比,国产之光正逐步闪耀

鸿蒙是面向5G物联网、面向全场景的分布式操作系统&#xff0c;其不是安卓系统的分支或修改而来的&#xff0c;与安卓、iOS是不一样的操作系统。鸿蒙将打通手机、电脑、平板、电视、电器设备、工业自动化控制、无人驾驶、车机设备 、智能穿戴统一成一个操作系统&#xff0c;并且…

前端加载访问速度优化(Nginx)

当前端部署文件过大时很容易造成网页加载慢的现象&#xff0c;为了提升加载速度&#xff0c;提供nginx的三种解决方案。 文章目录 1. gzip压缩2. 优化 keepalive 连接3.配置缓存注意事项总结 1. gzip压缩 往nginx.conf 的 http内容段落中加入 # gzip configgzip on;gzip_min_l…

SpringBoot之分层解耦以及 IOCDI的详细解析

### 3.2 分层解耦 刚才我们学习过程序分层思想了&#xff0c;接下来呢&#xff0c;我们来学习下程序的解耦思想。 解耦&#xff1a;解除耦合。 #### 3.2.1 耦合问题 首先需要了解软件开发涉及到的两个概念&#xff1a;内聚和耦合。 - 内聚&#xff1a;软件中各个功能模块内…

【算法系列篇】递归、搜索和回溯(四)

文章目录 前言什么是决策树1. 全排列1.1 题目要求1.2 做题思路1.3 代码实现 2. 子集2.1 题目要求2.2 做题思路2.3 代码实现 3. 找出所有子集的异或总和再求和3.1 题目要求3.2 做题思路3.3 代码实现 4. 全排列II4.1 题目要求4.2 做题思路4.3 代码实现 前言 前面我们通过几个题目…

(8)Linux Makefile | 依赖关系,依赖方法

&#x1f4ad;前言&#xff1a; 本篇文章会着重讲解Linux中的自动化构建代码工具: make/makefile的介绍与使用。 在Linux下编译代码时,每次都会输入 gcc code.c -o code.exe在删除可执行程序时,每次都会输入 rm -rf code.exe这样非常的不方便,很麻烦,于是乎学习自动化构建代…

Netty Review - ByteBuf 读写索引 详解

文章目录 概念Pre概述ByteBuf简介ByteBuf的主要特性结构APIByteBuf的创建读写操作示例引用计数操作其他常用操作 Code 演示 概念 Pre Netty Review - 探索ByteBuf的内部机制 概述 Netty的ByteBuf是一个强大的字节容器&#xff0c;用于处理字节数据。它提供了比Java标准库中的…

for命令语句

命令说明&#xff1a; 在批处理中&#xff0c;for是最为强大的命令语句&#xff0c;它的出现&#xff0c;使得解析文本内容、遍历文件路径、数值递增和递减等操作更加简单&#xff0c;配合if、call、goto等流程控制语句&#xff0c;更是可以实现脚本复杂的自动化、智能化操作。…

js基础入门

先来一点js基础&#xff0c;其实js大部分的时候都在处理对象或者数组。 对象四个基本操作&#xff1a;增删改查 掌握元素的增删改查&#xff0c;了解如何拷贝&#xff0c;深拷贝和浅拷贝的区别。详情见代码 <script>//创建对象一共有三种赋值声明的语法let obj{} //赋值…

Relocations for this machine are not implemented,IDA版本过低导致生成汇编代码失败

目录 1、问题描述 2、安卓app发生崩溃&#xff0c;需要查看汇编代码上下文去辅助分析 3、使用IDA打开.so动态库文件&#xff0c;提示Relocations for this machine are not implemented 4、IDA版本较老&#xff0c;不支持ARM64的指令集&#xff0c;使用7.0版本就可以了 5、…

【数据结构】二叉树的模拟实现

前言:前面我们学习了堆的模拟实现&#xff0c;今天我们来进一步学习二叉树&#xff0c;当然了内容肯定是越来越难的&#xff0c;各位我们一起努力&#xff01; &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:数据结构 &#x1f448; &…

创建个人网站(二)前端主页设计和编写一(太阳移动)

前言 以下内容纯纯当乐子来看就行&#xff0c;知识分享一下这样设计的原因&#xff0c;想看正文直接见下一节 为什么创建个人网站一之后几天没有动静了呢&#xff0c;一个是家里有事实在比较忙&#xff0c;第二个原因是没想到主页要设计成什么样&#xff0c;知道前两天问我姐什…

0基础学java-day22(多用户即时通信系统)

一、QQ 聊天项目演示 聊天通讯系统 在运运行过程出现的异常&#xff0c;应该是类的序列化不一致导致的 1 项目 QQ 演示 2 为什么选择这个项目 只做核心部分&#xff0c;界面相对弱化 3 项目开发流程 3.1 需求分析 3.2 界面设计 3.2.1 用户登录 3.2.2 拉取在线用户列表 …

对偶问题笔记(1)

目录 1 从 Lagrange 函数引入对偶问题2. 强对偶性与 KKT 条件3. 对偶性的鞍点特征 1 从 Lagrange 函数引入对偶问题 考虑如下优化问题 { min ⁡ f 0 ( x ) s . t f i ( x ) ≤ 0 , i 1 , ⋯ , p , h j ( x ) 0 , j 1 , ⋯ , q , x ∈ Ω , \begin{align} \begin{cases}\min…

Mimikatz 的使用(黄金票据的制作)

#江南的江 #每日鸡汤&#xff1a;孤独没有什么反义词&#xff0c;但他的近义词是自由&#xff0c;人生成功的道路上充满了孤独&#xff0c;那么也同样告诉你&#xff0c;你离成功后的自由不远了。 #初心和目标&#xff1a;在网络安全里高出名堂。。。 Mimikatz 本文分为两种…

kafka启动报错“输入行太长。 命令语法不正确“

下午想试一下本地安装启动一下 kafak&#xff0c;参考网上的安装文档&#xff0c;结果一直报错&#xff0c;最开始报的是这个错误&#xff1a; Classpath is empty. Please build the project first e.g. by running gradlew jarAll参考了很多网上的解决办法&#xff0c;最后…

科创金融的向善力量:浙商银行多措并举赋能科创企业,打造科技金融服务生态圈

近日&#xff0c;浙商银行科技金融服务发布会在杭州举行。 发布会以“智汇科创&#xff0c;善行未来”为主题&#xff0c;围绕科技金融服务“向善”新生态&#xff0c;浙商银行重磅推出科创企业全图景服务方案&#xff0c;正式发布科创积分贷&#xff0c;与浙江大学联合发布人…

【开源软件】最好的开源软件-2023-第五名 JHipster

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…