【算法设计与分析】动态规划:数塔问题


题目要求

提示:头歌 算法作业 实验七 动态规划 第1关:数塔问题

本关任务:编写用动态规划解决数塔问题。
在这里插入图片描述


一、解题关键要点(头歌题目已经给)

在这里插入图片描述

在这里插入图片描述

二、解题过程

1.关于数塔问题的动态规划过程自分析【重点】

求解过程(自底向上)

在这里插入图片描述

决策结果输出过程(自顶向下)

将上述分析求解过程角标记录为path数组 ,方便顺序输出结果

2.解题代码

代码如下(不知题目给出三维数组的a的第三维我用处,去除):

#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]);
	
}

3.运行结果

在这里插入图片描述


总结

上课没好好听这块😶‍🌫️,到做题了,瞎揣一气,望指正😢

  • 8
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
数塔问题是一个经典的动态规划问题,它的描述如下:给定一个由n行数字组成的数塔,如下图所示,从顶部出发,在每个节点可以选择向左或向右走,依次走到底部,使得所经过的数字之和最大。每次只能走到下一行相邻的两个节点。 ``` 5 8 4 3 6 9 7 2 9 5 2 8 4 1 7 ``` 使用动态规划思想,可以得到以下解题步骤: 1. 定义状态:设f[i][j]表示从第i行第j个数字开始走到最后一行所能得到的最大数字之和。 2. 状态转移方程:对于第i行第j个数字,其下一行相邻的数字为f[i+1][j]和f[i+1][j+1],那么状态转移方程为f[i][j] = max(f[i+1][j], f[i+1][j+1]) + a[i][j],其中a[i][j]表示第i行第j个数字的值。 3. 初始状态:对于最后一行的每个数字,其状态值为其自身的值,即f[n][j] = a[n][j]。 4. 求解目标:最终的目标是求解f[1][1],即从顶部开始走到底部所能得到的最大数字之和。 根据上述步骤,可以使用以下的动态规划代码实现数塔问题的求解: ```python # 假设a为一个n行n列的二维数组,表示数塔的数字 def max_sum(a): n = len(a) f = [[0] * n for _ in range(n)] # 初始化最后一行状态值 for j in range(n): f[n-1][j] = a[n-1][j] # 从倒数第二行开始逐行计算状态 for i in range(n-2, -1, -1): for j in range(i+1): f[i][j] = max(f[i+1][j], f[i+1][j+1]) + a[i][j] # 返回顶部节点的状态值 return f[0][0] ``` 以上代码的时间复杂度为O(n^2),空间复杂度为O(n^2),可以通过数塔问题的所有测试用例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值