1、题目描述
数字分布呈金字塔形状,从节点下滑过程中累加对应的数值,在任意一个节点,可往左下滑,也可以往右下滑,求最大下滑累加值。
2、解决思路
算法:动态规划
决策:左下滑、右下滑
状态:下滑累加值、访问状态
按照金字塔结构,划分为多层,每层的节点数量为k个(k为当前层数),节点的值保存在一个一维数组pyramid[n]中,n为节点总数。
如何遍历每一层的节点?
节点索引值i与节点所在层数n的关系
当前节点往左下滑,下层节点与当前节点索引的关系
(n为当前层数)
当前节点往右下滑,下层节点与当前节点索引的关系
(n为当前层数)
利用两个状态数组记录下滑过程中当前层的状态:
- 记录节点当前累计值(即下滑过程中的累加值)
- 记录节点是否已访问
当达到最后一层时,即可得到最大值,因此,只需要在最后一层中遍历所有节点累加值就可以得到最大下滑累加值。
3、代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int get_pyramid_index(int r, int j);
int get_left_node_index(int r, int idx);
int get_right_node_index(int r, int idx);
void set_node_state(int state[], int pyramid[], int visited[], int idx1, int idx2);
// Memory model of `pyramid`:
// `pyramid` is a one-dimensional array containing the elements of a pyramid with `rows` levels,
// in direct succession from left to right, top to bottom
int pyramid_slide_down(int num_elements, const int pyramid[num_elements], int rows)
{
int largest = 0;
int *state = NULL;
int *visited = NULL;
int r = 0, i = 0;
int idx = 0;
int idx_l = 0, idx_r = 0;
if(1 == num_elements || 1 == rows)
{
return pyramid[0];
}
state = (int*)malloc(num_elements * sizeof(int)); // 记录节点当前总值状态
visited = (int*)malloc(num_elements * sizeof(int)); // 记录节点访问状态
memset(state, 0, num_elements * sizeof(int));
memset(visited, 0, num_elements * sizeof(int));
state[0] = pyramid[0];
visited[0] = 1; // 已访问
for(r = 1; r < rows; r++) // 遍历层数
{
// 决策:往左下滑
for(i = 0; i < r; i++) // 遍历每一层的数据
{
idx = get_pyramid_index(r, i); // 得到本层节点在pyramid数组的索引
idx_l = get_left_node_index(r, idx); // 得到左子节点在pyramid数组的索引
set_node_state(state, pyramid, visited, idx, idx_l);
}
// 决策:往右下滑
for(i = 0; i < r; i++) // 遍历每一层的数据
{
idx = get_pyramid_index(r, i);
idx_r = get_right_node_index(r, idx);
set_node_state(state, pyramid, visited, idx, idx_r);
}
}
// 在最后一层中寻找最大值
largest = state[num_elements - 1];
for(i = num_elements - 1; i > num_elements - rows - 1; i--)
{
if(state[i] > largest)
{
largest = state[i];
}
}
free(state);
free(visited);
return largest;
}
int get_pyramid_index(int r, int i)
{
return(i + (r*(r-1))/2);
}
int get_left_node_index(int r, int idx)
{
return(idx + r);
}
int get_right_node_index(int r, int idx)
{
return(idx + r + 1);
}
void set_node_state(int state[], int pyramid[], int visited[], int idx1, int idx2)
{
int tmp_state = state[idx1] + pyramid[idx2];
if(visited[idx2] == 0) // 未访问过
{
state[idx2] = tmp_state;
visited[idx2] = 1;
}
else
{
// 只有当值比之前的值大时,才替换,确保最后结果为最大值
if(tmp_state > state[idx2])
{
state[idx2] = tmp_state;
}
}
return ;
}