有一个N层数塔,顶层只有一个结点,每向下一层增加一个结点,最底层有N个结点(下图给出了一个5层数塔)。从顶层出发,每个结点可以选择向左下或者向右下行走,一直走到底层。要求找到一条路径,使得路径上的数值之和最大。例如,下图所示的5层数塔的最大和及其路径为:60=8+15+9+10+18。
输入格式:
输入在N+1进行,首先给出数塔的高度值N。接下来的N行输入数塔各层结点的值,第一行给出顶层结点的一个值,每向下一行增加一个值,每行的值之间用空格间隔。
输出格式:
按照如下格式输出最大值及其路径。
最大值[结点-->结点-->... ... -->结点]输入样例:
5 8 12 15 4 9 5 8 10 5 13 16 7 18 10 9
输出样例:
60[8-->15-->9-->10-->18]
数塔问题求解思路
问题:数塔求解最优路径
输入:一个二维数组tower[size][size],数塔数据存放在tower的下三角内。
输出:一条最优路径存储在一维数组path[size]中。算法步骤:
1.定义一个辅助表格sum[size][size],存储数塔每个节点的最优路径数值和。
2.初始阶段计算:将数塔tower最底层的size个节点值填入辅助表格sum的最底层对应位置。
2.1列号col从0到size-1,逐个处理。
2.2 tower[size-1][col]-->sum[size-1][col]
3.行号row从size-2到0,逐行处理:
3.1 列号col从0到row,逐个处理:
3.2 sum[row][col]= max{sum[row+1][col],sum[row+1][col+1]}+tower[row][col]
4.定义最优路径数组path[size],初始path[0]=tower[0][0]。初始列号col=0.
5.行号row从1到size-1,逐行如下处理:
/5.1 比较sum[row][col]和sum[row][col+1]大小,选择较大数值对应的列号x
5.2 令path[row]=tower[row][x]
5.3 令col=x6.输出path数组
代码如下:
#include <stdio.h> int max(int a ,int b) { return a > b ? a : b; } int main() { int N; scanf("%d", &N); int tower[10][10]; long sum[10][10]; for (int i = 0; i < N; ++i) { for (int j = 0; j <= i; ++j) { scanf("%d", &tower[i][j]); } } for (int j = 0; j < N; ++j) { sum[N-1][j] = tower[N-1][j]; } for (int i = N-2; i >= 0; --i) { for (int j = 0; j <= i; ++j) { sum[i][j] = max(sum[i+1][j], sum[i+1][j+1]) + tower[i][j]; } } int path[10]; path[0] = tower[0][0]; int col = 0; for (int i = 1; i < N; ++i) { int x = col; if (sum[i][col+1] > sum[i][col]) { x = col+1; } path[i] = tower[i][x]; col = x; } printf("%ld[", sum[0][0]); printf("%d", path[0]); for (int i = 1; i < N; ++i) { printf("-->%d", path[i]); } printf("]\n"); return 0; }
5层数塔运行没有问题
6层数塔运行测试或者我自己放在编译器里都没有问题,但是会提示答案错误,本来以为是越界了,我就将数塔定义为长整型、长长整形结果还是不对,
运行测试用例是对的,不知道哪儿出问题了。后面我也将数塔进行了改进。
改进后的数塔
使用动态内存分配,根据输入的数塔高度动态分配二维数组的大小。
考虑错误处理,确保程序能够正确处理各种异常情况。
考虑使用更通用的数据结构和算法,以处理更大规模的数塔。
#include <stdio.h> #include <stdlib.h> int max(int a, int b) { return a > b ? a : b; } int main() { int N; scanf("%d", &N); if (N <= 0) { return 1; } int **tower = (int **)malloc(N * sizeof(int *)); for (int i = 0; i < N; ++i) { tower[i] = (int *)malloc((i + 1) * sizeof(int)); } long **sum = (long **)malloc(N * sizeof(long *)); for (int i = 0; i < N; ++i) { sum[i] = (long *)malloc((i + 1) * sizeof(long)); } for (int i = 0; i < N; ++i) { for (int j = 0; j <= i; ++j) { scanf("%d", &tower[i][j]); } } for (int j = 0; j < N; ++j) { sum[N - 1][j] = tower[N - 1][j]; } for (int i = N - 2; i >= 0; --i) { for (int j = 0; j <= i; ++j) { sum[i][j] = max(sum[i + 1][j], sum[i + 1][j + 1]) + tower[i][j]; } } int *path = (int *)malloc(N * sizeof(int)); path[0] = tower[0][0]; int col = 0; for (int i = 1; i < N; ++i) { int x = col; if (sum[i][col+1] > sum[i][col]) { x = col+1; } path[i] = tower[i][x]; col = x; } printf("%ld", sum[0][0]); printf("[%d", path[0]); for (int i = 1; i < N; ++i) { printf("-->%d", path[i]); } printf("]\n"); for (int i = 0; i < N; ++i) { free(tower[i]); free(sum[i]); } free(tower); free(sum); free(path); return 0; }
数塔改进后依旧无法正确处理六层数塔的问题,有没有大佬可以帮我看一下更正一下。