算法第三章上机实践报告

  引论:这是第二次在算法课上的上机实践了,虽然逐渐有了思考算法的感受,但这一次上机实践仍是并不轻松。关键在于在实验课前对第三章的知识掌握得还不足够,常常会由于明明知道理论上如何解题而苦于没法将其实现。不过,经过本次上机实践,个人收获是很是丰富的,下面用实践课题目中的第一题《数字三角形》开始分享个人经验。ios

1、实践题目

给定一个由 n行数字组成的数字三角形以下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径通过的数字总和最大。算法

QQ截图20170929023616.jpg

输入格式:

输入有n+1行:编程

第 1 行是数字三角形的行数 n,1<=n<=100。数组

接下来 n行是数字三角形各行中的数字。全部数字在0-99 之间。函数

输出格式:

输出最大路径的值。flex

输入样例:

在这里给出一组输入。例如:spa

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

输出样例:

在这里给出相应的输出。例如:30设计

 

2、问题描述

  初看这一道题的时候,差点陷入到了迷惑之中,不过简单分析一下题目后发现是那样的熟悉——题目要求咱们从数字三角形的最顶端数字开始,选取一条可以使通过的数字总和最大的路径。而这不就和老师在第三章开头课说的例子同样吗?从A地到D地选取一条通过B、C两地的最短路径。A到D的最短路径取决于B到D,而B到D取决于C到D。咱们将这种思想反推至这道题目,要求出数字三角形的最短路径,从顶部数字开始到底部数字,这要先取决于顶部数字到第二行的最大和,再取决于第二行数字到第三行的最大和,以此类推至数字三角形的最后一行。好的,有了这种动态规划的思想咱们离解决问题还有一半距离了!code

那么咱们开始分析,由于每一行的最大和都取决于上一行的数字最大和,那么,咱们自底而上分析,重填输入进来的二维数组。重写时,数字三角形的最后一行是不变的,由于最后一行的数字们没有下面一行的数字影响,而从倒数第二行开始,这些数字重写后变为,它自身与和它相邻的最后一行两个数字之和的最大值。举个例子,即a[i][j]的大小是max{(a[i+1][j] + a[i][j]), (a[i+1][j+1])}。那么咱们自下而上重写数组,最后获得新的最顶端的数字,便是最大值路径。blog

 

3、算法描述

  首先列出我解题的代码

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int num;
 8     cin>>num;
 9     const int n = num;
10     int array[n][n];
11     
12     for (int i = 0; i < n; i++)
13     {
14         for (int j = 0; j <= i; j++)        //按数字三角型的形式,填充二维数组(矩阵)的下三角 
15         {
16             cin>>array[i][j];
17         }
18     }
19     
20     //用动态规划的思想,改写array二维数组 
21     for (int i = n - 2; i >= 0; i--)    //由于数字三角形的最后一行的动态规划最大值是本身,因此从倒数第二行开始求自下而上时的动态规划最大值 
22     {
23         for (int j = 0; j < i + 1; j++)
24         {
25             array[i][j] = max((array[i + 1][j] + array[i][j]), (array[i + 1][j + 1] + array[i][j]));    //当前元素的动态规划最大值是判断它自己和它左下边或右下边的数字相加的最大值 
26         }
27     }
28     cout<<array[0][0];    //由于是自下而上求最大值,因此二维数组第一个元素便是数字三角形的最大值 
29     return 0;
30 }

  由于改写后的数组,数字三角形的最后一行是不变的,因此咱们的第一层循环从倒数第二行开始,所以定义i = n - 2,并让i不断变小;在第二层循环中,咱们分析的是当前行的每一个数字,每一行的数字数目为该行行号,而i为每一行的下标,因此定义j = i + 1。而咱们填入数组的是该行数字和与它相邻的下一行数字组成之和的最大值。最终循环结束后,咱们直接输出数组的第一个数字,即获得最大路径和。

 

4、算法时间及空间复杂度分析

  对于时间复杂度:本算法为main函数中的重叠的两个for循环,而第一层循环是从n-2开始至0,第二层循环为从0开始至n-1,所以不可贵出,本算法的时间复杂度为O(n^2)。

  对于空间复杂度:由于本题是直接改写输入进来二维数组,因此没有额外申请数组和内存空间,因此空间复杂度为O(1)。

 

5、心得体会

  经过本次上机实践,我更好地巩固了第三章的知识,动态规划思想理解起来不难,但须要屡次的动手实践来让本身真正掌握它。经过本身动手编程解决这一道题让我加深了上节课所学知识的印象。在想出上述解题算法以前,我在草稿本上列出了不少种填表的方式,但难以实现出来,即便解决了这一道题,我目前对填表法的掌握还并不熟练。不过,经过作这一道实验题,我真正明白了动态规划思想的厉害之处。由于实验题目集中的第二题是书上的原题,因此相对于第二题,我在第一题花费的时间较多。所以,在解决动态规划思想的题目中,咱们不能纠结于如何写出完完整整的递推式,而要多结合题目实际。

同时,解决这道题目也不只仅是我一我的想出来的,这道题目的核心思想是个人搭档为我讲解的,所以光靠本身一我的我是没法解决这道题目的。这又再次体现出结对编程的重要性,两我的的头脑风暴得出来的结果是实验课中最好的成果。

经过本次实验,我但愿本身可以再接再砺,不断钻研算法知识,争取解决更多的问题!

相关文章
相关标签/搜索