对于数字三角形这个问题的要求:
题目分析:
我们可以把问题分成两部分:
1.怎么构建出来这个三角形,怎么构建才能让我下面的运算更加简单
2.如何设计程序能够使其计算出来最大的数
重点信息:向左走的次数与向右走的次数相差不能超过1
拆解分析:
怎么构建这个数字三角形?
在这个题目的输入示例中其实有一定的提示信息,示例里的三角形长这个样子:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
这个是一个靠左的直角三角形,相较于开头的等腰三角形让我们更能想起来二维数组这一概念,空白部分只不过是没有被输入(这一点我们可以通过for循环进行控制),因此我们思路是:
以创建二维数组的方式来构建一个矩阵,再使用for循环对需要输入数据的位置进行scanf数据输入
tips:对于笔者妄图使用动态的方式进行数组创建,但忘记了数组的行列必须填入常数,而不是填入一个变量。在题干中我们也发现了提示,行数最多为100行,因此我们可以创建101行来进行数据的存储。(笔者的程序从第二行 第二列开始进行数据的填入,为了便于后期定位元素位置,且1开始进行填入更加符合认知)
如何设计程序能够使其计算出来最大的数?
我们对于寻找计算最大数的路径的方法是:
在创建三角形数组的时候(三角数组),同时也创建一个相同的二维数组用于存放各个路径下的和(加和数组)。
对于和的计算,我们选取它上级相邻的两个数中较大的一个数。
对于加和的方式我们有三种可能:
如果向下检索,检索的列在最左边,那这个位置:
该位置的加和数组的值=正上方的家和数组的值+这个位置的三角数组的值
如果向下检索过程中,检索列在该行的最右边,那个位置:
该位置的加和数组的值=上一层最右边的加和数组的值+这个位置的三角数组的值
如果向下检索过程中,检索列不在最左或者最右,那个位置:
该位置的加和数组的值=这个位置的三角数组的值+上一层相邻的两个数之间的较大值
如此方法一层层计算,加和数组也将被填满,而加和数组里的每个元素都是在当前路径下的最大和。
选择数据:
加和数组被填满后,如何选择题目要求的最大值呢?
毫无疑问的是,所谓的最大值一定在加和数组的最后一行里。
在上文的分析里,我们提到了一个重点:
重点信息:向左走的次数与向右走的次数相差不能超过1
由此推理出:
因此我们可以想象,如果是奇数行,那走的次数一定为偶数次
如果是偶数行,那走的次数一定是奇数次。
结论+数据选择方法:
因此在走奇数次时(偶数行),他们的最大值一定在加和数组里最后一行的中间两个数。
在走偶数次时(奇数行),他们的最大值一定在加和数组里最后一行里的最中间的那个数。
代码如下:
#include<stdio.h>
int main()
{
int n = 0;
int arr[101][101];
int add[101][101];
printf("请输入行数:");
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
scanf("%d", &arr[i][j]);
}
}
add[1][1] = arr[1][1];
for (int i = 2; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (j == 1)
{
add[i][j] = add[i - 1][j] + arr[i][j];
}
else if (i == j)
{
add[i][j] = add[i - 1][j - 1] + arr[i][j];
}
else
{
if (arr[i - 1][j] > arr[i - 1][j - 1])
{
add[i][j] = arr[i][j] + add[i - 1][j];
}
else
{
add[i][j] = arr[i][j] + add[i - 1][j - 1];
}
}
}
}
if (n % 2 == 1)
{
printf("max=%d \n", add[n][n / 2 + 1]);
}
else
{
if (add[n][n / 2] > add[n][n / 2 + 1])
{
printf("max=%d \n", add[n][n / 2]);
}
else
{
printf("max=%d \n", add[n][n / 2 + 1]);
}
}
return 0;
}