动态规划 数字三角形(递归,递推,记忆化搜索)

题目要求:

7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

  在上面的数字三角形中寻找在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。
  三角形的行数大于1小于等于100,数字为 0 - 99

输入格式:
5 //三角形行数。下面是三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

解题思路:

  用二维数组存放数字三角形

  D[r][j] //表示第i行第j个元素的数值;

  MaxSum(i,j) //表示从根部到第i行最大路径的,所有数值的最大和;

用递归的思想,在D(i,j)位置,下一个能走的位置为D(i+1,j)和D(i+1,j+1),进行递归

  MaxSum(i,j)=max(MaxSum(i+1,j),MaxSum(i+1,j+1))+D[i][j];

递归代码如下:

 1 #include "stdio.h"
 2 #define MAX 100
 3
 4 int n;
 5 int D[MAX][MAX];
 6
 7 int main(){
 8
 9     int i,j;
10
11     printf("Input N:\n");
12     scanf("%d",&n);
13
14     for(i=1;i<=n;i++)
15     {
16         for(j=1;j<=i;j++)
17         {
18             scanf("%d",&D[i][j]);
19         }
20         printf("\n");
21     }
22
23     printf("Max is %d",MaxSum(1,1));
24 }
25
26 int MaxSum(int i,int j)
27 {
28     if(i==n)
29         return D[i][j];
30     int x=MaxSum(i+1,j);
31     int y=MaxSum(i+1,j+1);
32     return max(x,y)+D[i][j];
33 }
34
35 int max(int m,int n){
36     return m>n?m:n;
37 }

算法评价,因为采用的是递归的算法,深度遍历每条路径,存在大量的重复运算,效率较低,如果共用n行,时间复杂度O(n)=2的n次方。

如:在计算时d(3,2)被重复调用

d(2,1)   的计算会调用--> d(3,1) , d(3,2)

d(2,2)   的计算会调用--> d(3,2) , d(3,3)

所以我们对代码进行了改进

记忆化搜索,记忆型动态规划程序,引入一个maxSum[i][j]用来存放每一个MaxSum(i,j)的值,等到需要用的时候,记忆化搜索使用。这时的时间复杂度O(n)= n(n+1)/2

 动态化代码如下:

 1 #include "stdio.h"
 2 #define MAX 100
 3
 4 int n;
 5 int D[MAX][MAX];
 6 int maxsum[MAX][MAX];
 7
 8 int main(){
 9
10     int i,j;
11
12     printf("Input N:\n");
13     scanf("%d",&n);
14
15     for(i=1;i<=n;i++)
16     {
17         for(j=1;j<=i;j++)
18         {
19             scanf("%d",&D[i][j]);
20            maxsum[i][j]=-1;
21         }
22     }
23
24     printf("Max is %d",MaxSum(1,1));
25 }
26
27 int MaxSum(int i,int j)
28 {
29     if(maxsum[i][j]!=-1)
30         return maxsum[i][j];
31     int x=MaxSum(i+1,j);
32     int y=MaxSum(i+1,j+1);
33     maxsum[i][j]=max(x,y)+D[i][j];//用来存储到(i,j)位置的值。
34     return maxsum[i][j];
35 }
36
37 int max(int m,int n){
38     return m>n?m:n;
39 }

递推方法:明天补充

总结:

1.递归到动态的一般转换方法:

  递归函数有n个参数,就定义一个n维的数组,数组的下标是递归函数参数的取值范围,数组元素的值是递归函数的返回值,这样就可以从边界值开始,逐步填充数组,相当于计算递归函数值的逆过程。

2.动规解题的一般思路:

  1)将原问题分解成若干个子问题。子问题和原问题结构一样,只是规模变小,而每个子问题解决之后,将结果保存起来。

  2)确定状态。我们往往将和子问题相关的各个变量的一组取值,称之为一个“状态”。一个“状态”对应于一个或多个子问题,所谓某个“状态”下的“值”,就是这个“状态”所对应的子问题的解。所有“状态”的集合,构成问题的“状态空间”。“状态空间”的大小,与用动态规划解决问题的时间复杂度直接相关。

  3)确定一些初始状态(边界状态)的值。在“三角形问题”中,初试状态就是底边状态,初始状态的值就是底边的值。

  4)确定状态转移方程。就是从一个状态转移到另一个状态的过程。

转载请注明出处。新人求关注。

时间: 2024-12-24 06:11:33

动态规划 数字三角形(递归,递推,记忆化搜索)的相关文章

HDU4919 Exclusive or(递推+记忆化搜索+大数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4919 题意: 给定n求sigma(i^(n - i)) (1<=i<=n-1) 分析: 打表后可以发现规律 1) n = 2 * k + 1; f[n] = 4 * f[k] + 6; 2) n = 2 * k f[n] = 2 * f[k] + 2 * f[k-1] + 4 * k - 4; 具体的证明:http://blog.csdn.net/houserabbit/article/detai

Bailian1664 Placing apples【递推+记忆化递归】

1664:Placing apples 总时间限制: 1000ms 内存限制: 65536kB 描述 We are going to place M same apples into N same plates. There could be some empty plates. How many methods do we have? When we have 7 applesand 3 plates, the methods, (1, 5, 1) and (5, 1, 1) are the

第五第六课------递推+记忆话搜索+搜索八皇后(思想是做梦)+各种剪枝思想

搜索是一个漫长的过程贯彻整个oi: 八皇后------- #include <bits/stdc++.h>#define inf 0x7fusing namespace std;int n,ans,a[inf],b[inf],c[inf],d[inf];void print(){ ++ans; if(ans<=3){ for(int i=1;i<=n;i++) cout<<d[i]<<" "; cout<<endl; }} v

hihocoder1037(记忆化搜索)

题目连接:点击打开链接 解题思路: 和白书上的数字三角形一样,用记忆化搜索解决,推出转移方程dp[i][j] = g[i][j] + max( d( i + 1 , j ) , d( i + 1 , j + 1) ); 完整代码: #include <iostream> #include <cstdio> #include <cstring> #include <climits> using namespace std; const int maxn = 1

数字三角形——递归、递推、记忆化搜索

数字三角形 描述: 有一个由非负整数组成的三角形,第一行只有一个数,除了最下行之外没个数的左下方和右下方各有一个数. 问题: 从第一行的数开始,每次可以往左下或右下走一格,直到走到最下行,把沿途经过的数全部加起来.如何走才能使得这个和尽量大? 分析: 不难看出此题是一个动态的决策问题:每次有两种选择--左下或右下.如果用回溯法求出所有的可能的路线,就可以从中选出最优的路线.但和往常一样,回溯法的效率太低:一个n层数字三角形的完整路线有2^n条,当n很大时回溯法的速度将让人无法忍受.因此本题讨论用

[hdoj]1244记忆化搜索

题解参考:http://www.cnblogs.com/peaceful-andy/archive/2012/08/14/2638907.html 很久很久以前……我一直以为记忆化搜索就是dp,dp就是记忆化搜索……多么悲哀的认识…… 动态规划是“填表格”的顺序依次递推,记忆化搜索说白了就是搜索的一种,树型,二者的相同点就是,边运行边记忆,对于计算过的都存起来,不再重复计算. 1 #include <iostream> 2 using namespace std; 3 4 const int

动态规划&mdash;&mdash;数字三角形(递归or递推or记忆化搜索)

动态规划的核心就是状态和状态转移方程. 对于该题,需要用抽象的方法思考,把当前的位置(i,j)看成一个状态,然后定义状态的指标函数d(i,j)为从格子出发时能得到的最大和(包括格子本身的值). 在这个状态定义下,原问题的解就是d(i,j). 下面看一下不同状态之间如何转移.从格子(i,j)出发有两种策略.如果向左走,则到(i+1,j)后需要求"从(i+1,j)出发能得到的最大和"这一问题,即d(i+1,j). 类似的,往右走之后需要求解d(i+1,j+1).由于可以在这两个决策中自由选

由DAG到背包问题——记忆化搜索和递推两种解法

一.问题描述 物品无限的背包问题:有n种物品,每种均有无穷多个.第 i 种物品的体积为Vi,重量为Wi.选一些物品装到一个容量为 C 的背包中,求使得背包内物品总体积不超过C的前提下重量的最大值.1≤n≤100, 1≤Vi≤C≤10000, 1≤Wi≤1000000. 二.解题思路 我们可以先求体积恰好为 i 时的最大重量(设为d[i]),然后取d[i]中的最大值(i ≤ C).与之前硬币问题,"面值恰好为S"就类似了.只不过加了新属性--重量,相当于把原来的无权图改成带权图,即把&q

hdu4283 You Are the One 区间dp 记忆化搜索or递推

You Are the One Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3032    Accepted Submission(s): 1352 Problem Description The TV shows such as You Are the One has been very popular. In order to