赞
踩
目录
今天我们接着解决一个问题,也就是求数字三角形路径最大的问题,下面我会详细讲解这个问题的解决思路,以及通过代码的方式去解决这个问题,下面接着看。
给出了一个数字三角形,从三角形的顶部到底部有多条不同的路径。 对于每条路径,把路径上面的数加起来可以得到一个和,累加和最大的路径称为“最佳路径”。
样例输入:
第一行是数塔层数N(1<=N<=100)。
第二行起,从一个数字按数塔图形依次递增,共有N层。
5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11最大路径输出结果:86
对于这一类问题我们很容易想到去通过递归的方式来解决,先创建一个二维数组来储存这些数据, 然后去通过递归比较大小,取其中比较大的进入到下一层递归,也就是当前节点加上其左边和右边节点较大者。
- #include<stdio.h>
- #include<stdlib.h>
- //比较获取最大值
- int max(int a, int b) {
- return a > b ? a : b;
- }
- //递归函数
- int fun(int n, int i, int j, int** a) {
- //如果递归到最上一层的话就直接返回0即可
- if (i == n) {
- return 0;
- }
- //进入到递归,当前数字加上左右两边的较大者
- return a[i][j] + max(fun(n, i + 1, j, a), fun(n, i + 1, j + 1, a));
- }
-
- int main()
- {
- int n;
- printf("enter your num:");
- scanf("%d", &n);
- //创建二维数组储存数据
- int** data = (int**)malloc(sizeof(int*) * n);
- for (int i = 0; i < n; i++) {
- data[i] = (int*)malloc(sizeof(int) * n);
- }
- //初始化二维数组为0
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <= i; j++) {
- data[i][j] = 0;
- }
- }
- //输入数据
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <= i; j++) {
- scanf("%d", &data[i][j]);
- }
- }
- //结果
- int result= fun(n, 0, 0, data);
- printf("最大路径是%d\n", result);
- }
-
结果如下:
前面讲到去通过递归的方式来实现这个算法,很明显其时间复杂度为O(2^n),但是如果递归的深度过深的话,也就是说输入的数据很多的话就很容易出现系统计算量过大卡死。对此我们可以通过优化递归的代码来减少时间复杂度,我们可以去创建一个记忆数组来储存前面所递归的结果。举个例子,对于斐波那契数列1 1 2 3 5……,我们可以用递归算法去实现,同样的如果要往很后面算的话也会面临这个问题,如果我们创建这么一个数组array来储存前两个数据的话,到时候我们直接拿出来用就行了比如当前array储存了2和3,那么我要算5的时候就拿出来相加就行了,不需要重新去递归计数2和3了,这时候时间复杂度变为O(n^2)
既然有了这么一个记忆数组,那么我们还可以去通过这个记忆数组来输出这个路径,代码如下:
- #include<stdio.h>
- #include<stdlib.h>
- //比较大小
- int max(int a, int b) {
- return a > b ? a : b;
- }
- //递归函数,二维数组op是记忆数组,初始化为0,表示没有访问过
- int fun(int n, int i, int j, int** a, int** op) {
- if (i == n) {
- return 0;
- }
- //如果记忆数组储存了前面的数据,直接返回就行了
- if (op[i][j] != 0)
- return op[i][j];
-
- op[i][j] = a[i][j] + max(fun(n, i + 1, j, a, op), fun(n, i + 1, j + 1, a, op));
- return op[i][j];
- }
-
- //打印结果
- void print(int result,int**op,int n) {
- puts("");//换行
- //输出记忆数组op
- printf("记忆数组op结果如下:\n");
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) {
- printf("%d ", op[i][j]);
- }
- puts("");
- }
- printf("最大路径是:%d\n", result);
- }
-
- //输出路径
- void Find_path(int** op, int** a, int n) {
- int j = 0;
- printf("路径如下:\n");
- printf("%d", a[0][0]);
- for (int i = 1; i < n; i++) {
- int node = op[i - 1][j] - a[i - 1][j];//减去加上这个位置数字,得到的结果与其左右节对比是否相等
- if (node == op[i][j + 1])
- j++;
- printf("-->%d", a[i][j]);
- }
- }
-
- int main()
- {
- int n;
- printf("enter your num:");
- scanf("%d", &n);
- //创建二维数组储存数据
- int** data = (int**)malloc(sizeof(int*) * n);
- for (int i = 0; i < n; i++) {
- data[i] = (int*)malloc(sizeof(int) * n);
- }
- //初始化二维数组为0
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <= i; j++) {
- data[i][j] = 0;
- }
- }
- //输入数据
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <=i ; j++) {
- scanf("%d", &data[i][j]);
- }
- }
-
- //op记忆数组
- int** op = (int**)malloc(sizeof(int*) * n);
- for (int i = 0; i < n; i++) {
- op[i] = (int*)malloc(sizeof(int) * n);
- }
- for (int x = 0; x < n; x++) {
- for (int y = 0; y < n; y++)
- op[x][y] = 0;//初始化为0,表示未访问
- }
-
- int result = fun(n, 0, 0, data,op);
- print(result,op,n);
- Find_path(op, data, n);
- }
-
结果如下:
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
-
- int max(int a, int b) {
- return a > b ? a : b;
- }
-
- //非递归算法函数
- void find(int n, int** a, int** op) {
- for (int j = 0, i = n - 1; j < n; j++) {
- op[i][j] = a[i][j];//先把最后一次数据放入到记忆数组op中
- }
- for (int x = n - 2; x >= 0; x--) {
- for (int y = 0; y <= x; y++) {
- int temp = max(op[x + 1][y], op[x + 1][y + 1]);
- op[x][y] = temp + a[x][y];
- }
- }
- }
-
- //获取路径储存到path数组当中
- void find_path(int n, int* path, int** op, int** a) {
- path[0] = a[0][0];
- int j = 0;
- for (int i = 1; i < n; i++)
- {
- int node = op[i - 1][j] - a[i - 1][j];
- if (node == op[i][j + 1])
- j++;
- path[i] = a[i][j];
- }
- }
-
- //输出结果
- void print(int* path, int n, int** op) {
- printf("记忆数组op结果如下:\n");
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++)
- printf("%d ", op[i][j]);
- printf("\n");
- }
- printf("路径如下:\n");
- for (int i = 0; i < n; i++)
- printf("%d-->", path[i]);
- printf("end\n");
- printf("最大路径是:%d\n", op[0][0]);
- }
-
-
- int main()
- {
- int n;
- printf("enter your num:");
- scanf("%d", &n);
- //创建二维数组储存数据
- int** data = (int**)malloc(sizeof(int*) * n);
- for (int i = 0; i < n; i++) {
- data[i] = (int*)malloc(sizeof(int) * n);
- }
- //初始化二维数组为0
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <= i; j++) {
- data[i][j] = 0;
- }
- }
- //输入数据
- for (int i = 0; i < n; i++) {
- for (int j = 0; j <=i ; j++) {
- scanf("%d", &data[i][j]);
- }
- }
-
- //op
- int** op = (int**)malloc(sizeof(int*) * n);
- for (int i = 0; i < n; i++) {
- op[i] = (int*)malloc(sizeof(int) * n);
- }
- for (int x = 0; x < n; x++) {
- for (int y = 0; y < n; y++)
- op[x][y] = 0;
- }
-
- //储存路径数组path
- int* path = (int*)malloc(sizeof(int) * n);
- memset(path, 0, sizeof(path));//初始化
-
- find(n, data, op);
- find_path(n, path, op, data);
- print(path,n,op);
- }
-
结果如下:
以上就是本期的全部内容了,我们下一次见!
分享一张壁纸:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。