动态规划——数塔问题(三维数组的应用)

这篇具有很好参考价值的文章主要介绍了动态规划——数塔问题(三维数组的应用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 一、例题要求及理论分析

声明:理论指导《算法设计与分析 第四版》

因为这个地方用到了三维数组,感觉很有意思就故意挑出来分享给大家(三维数组可以看成很多页二维数组)

4.5.1认识动态规划
数塔问题:
如图4-12所示的一个数塔,从顶层到底层或从底层到顶层,在每一结点可以选择向左走或是向右走,要求找出一条路径,使路径上的数值和最大。
问题分析:
(1)不难理解,这个问题用贪婪算法有可能会找不到真正的最大和。以图4-12为例就是如此。采用贪婪策略,无论是自上面下,还是自下而上,每次向下都选择较大的一个数移动,则路径和分别为:
三维数组 动态规划,# C语言算法,动态规划,算法
                                 数塔图
9+15+8+9+10=51(自上而下),19+2+10+12+9=52(自下而上)
都得不到最优解,真正的最和是:
9+12+10+18+10=59
(2)要找到最大和的前提条件是,要能看到数塔的全貌,下面的算法设计都是以此为前提的。
在知道数塔全貌的前提下,可以用枚举法或第5章将学习的搜索算法来解决问题。但从图中可以看出,在数塔层数为 n 时,要枚举的路径为2^(n-1)条。在 n 稍大的情况下,需要列举出的路径条数是一个非常庞大的数目。所以枚举法也不是一个适合此问题的算法策略。
(3)这个问题的原始数据是一个三角形的二维图形,而且问题的答案与各层数据间关系复杂,不适合用分治算法分解为与原问题相似的子问题。
下面就学习用动态规划解决此问题。
算法设计:动态规划设计过程如下。
1.阶段划分
从数塔问题的特点来看,不难发现解决问题的阶段划分,应该是自下而上逐层决策。不同于贪婪策略的是做出的不是唯一决策,第一步对于第五层的8个数据,做如下4次决策:
对经过第四层2的路径,在第五层的19,7中选择19;
对经过第四层18的路径,在第五层的7,10中选择10;
对经过第四层9的路径,在第五层的10,4中也选择10;
对经过第四层5的路径,在第五层的4,16中选择16。
这是一次决策过程,也是一次递推过程和降阶过程。因为以上的决策结果将5阶数塔题变为4阶子问题,递推出第四层与第五层的和为:
21(2+19),28(18+10),19(9+10),21(5+16)

用同样的方法还可以将4阶数塔问题变为3阶数塔问题……最后得到的1阶数问题,就是整个问题的最优解。
2、存储、求解
1)原始信息存储
原始信息有层数和数塔中的数据,层数用一个整型变量 n 存储,数塔中的数据用二维数组 data ,存储成如下的下三角阵:

9

12 15

10  6   8

2   18  9  5

19  7  10  4  16

2)动态规划过程存储
由于早期阶段动态规划决策的结果是一组数据,且本次的决策结果是下次决策的唯一依据(无后效性),所以必须在存储每一次决策的结果,若仅仅是求最优解,用一个一维数组存储最新的决策结果即可;但若要同时找出最优解的构成或路径,则必须用二维数组 d 存储各阶段的决策结果。根据上面的算法设计,二维数组 d 的存储内容如下:

 d [ n ][j]= data [ n ][j]    j=1,2,……,n;
 i = n -1, n -2,…,1, j =1,2,…, i 时
 d [ i ][ j ]= max ( d [ i +1][j], d [ i +1][j+1])+ data [ i ][j]
最后 d [1][1]存储的就是问题的结果。

二、代码

#include<stdio.h>
int main()
{
 int a [50][50][3], i , j , n ;
 printf (" please input the number of rows :\n");
 scanf("%d",&n);
 for ( i =1; i <= n ; i = i +1)
   for ( j =1; j <= i ; j = j +1)
    { 
        scanf("%d",&a [ i ][ j ][1]);
        a [ i ][ j ][2]= a [ i ][ j ][1];
        a [ i ][ j ][3]=0;
    }
 for ( i = n -1; i >=1; i = i -1)
   for ( j =1; j <= i ; j = j +1)
    if ( a [ i +1][ j ][2]> a [ i +1][ j +1][2])
        {
        a [ i ][ j ][2]= a [ i ][ j ][2]+ a [ i +1][ j ][2];
        a [ i ][ j ][3]=0;
        }
   else 
       {
       a [ i ][ j ][2]= a [ i ][ j ][2]+ a [ i +1][ j +1][2]; a [ i ][ j ][3]=1;
       }
   printf (" max =%d\n", a [1][1][2]);
    j =1;
for ( i =1; i <= n -1; i = i +1)
{ printf ( "%d->",a [ i ][ j ][1]);
 j = j + a [ i ][ j ][3];
}
 printf ("%d", a [ n ][ i ][1]);
 return 0;
}

三、运行结果 

三维数组 动态规划,# C语言算法,动态规划,算法文章来源地址https://www.toymoban.com/news/detail-777603.html

到了这里,关于动态规划——数塔问题(三维数组的应用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 贪心算法解决背包问题和动态规划解决0-1背包问题(c语言)

    运行结果如下: 运行结果如下: 总结: 贪心算法: 每一步都做出当时看起来最佳的选择,也就是说,它总是做出局部最优的选择。 贪心算法的设计步骤: 对其作出一个选择后,只剩下一个子问题需要求解。 证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安

    2024年02月04日
    浏览(40)
  • 动态规划算法解决背包问题,算法分析与C语言代码实现,时间效率解析

    🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨,经典算法的解析✨都在这儿,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 -  数据结构与算法_勾栏听曲_0 🍻欢迎大家  🏹  点赞👍  评论📨  收藏⭐️ 📌个人主

    2023年04月16日
    浏览(41)
  • 3.数组算法、动态规划

    Array是一个容器,可以容纳固定数量的项目,这些项目应该是相同的类型。大多数数据结构都使用数组来实现其算法。以下是理解Array概念的重要术语。 元素 - 存储在数组中的每个项称为元素。 索引 - 数组中元素的每个位置都有一个数字索引,用于标识元素。 可以使用不同语

    2024年02月16日
    浏览(30)
  • 【动态规划】两个数组问题

    题目链接 状态表示 dp[i][j] 表示 s1 0 到 i 区间内,以及时s2 0 到 j 区间内所有的子序列中,最长的公共子序列 状态转移方程 根据最后一个位置的请款分类讨论。 初始化 关于字符串的dp问题,空串是有研究意义的。引入空串的概念之后会方便我们的初始化 这里还可以使用之前

    2024年02月11日
    浏览(28)
  • 蓝桥杯-动态规划-子数组问题

    目录 一、乘积最大数组 二、乘积为正数的最长子数组长度 三、等差数列划分 四、最长湍流子数组 心得: 最重要的还是状态表示,我们需要根据题的意思,来分析出不同的题,不同的情况,来分析需要多少个状态 乘积最大数组 1.状态表示 dp[i]:到达i位置的最大乘积子数组。

    2024年02月05日
    浏览(27)
  • c++ 子数组动态规划问题

    1.最大子数组和   力扣 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 示例 1: 示例 2: 示例 3: 2.环形子数组最大和 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 给

    2024年02月12日
    浏览(27)
  • 两个数组的dp问题(2)--动态规划

      一)交错字符串: 97. 交错字符串 - 力扣(LeetCode) 一)确定一个状态标识: 如果我选择s1的一段区间,再进行选择s2得一段区间,那么s3这个字符串的长度就已经固定 预处理:在s1字符串s2字符串和s3字符串前面加上一个虚拟字符,让下标从1开始进行计数 如果要是从1号位置开始进

    2024年02月15日
    浏览(33)
  • 【动态规划】【数学】【C++算法】805 数组的均值分割

    视频算法专题 动态规划汇总 数学 给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 数组 或者 B 数组中,使得 A 数组和 B 数组不为空,并且 average(A) == average(B) 。 如果可以完成则返回true , 否则返回 false 。 注意:对于数组 arr , average(arr) 是 arr 的所有元素的和

    2024年02月20日
    浏览(34)
  • C++算法 —— 动态规划(7)两个数组的dp

    每一种算法都最好看完第一篇再去找要看的博客,因为这样会帮你梳理好思路,看接下来的博客也就更轻松了。当然,我也会尽量在写每一篇时都可以不懂这个算法的人也能边看边理解。 动规的思路有五个步骤,且最好画图来理解细节,不要怕麻烦。当你开始画图,仔细阅读

    2024年02月07日
    浏览(44)
  • 力扣 53. 最大子数组和(C语言+分治递归、动态规划)

            给你一个整数数组  nums  ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组  是数组中的一个连续部分。         示例 1:         示例 2:         示例 3: (1)分治递归         分治法的核心部分。

    2024年02月07日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包