滑雪问题
滑雪问题
1. 题目描述:
Michael喜欢滑雪,这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:
1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
输入格式:
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
输出格式:
输出最长区域的长度。
输入样例:
5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
输出样例:
25
2. 题目解析:
问题理解与状态定义
题目给定了一个二维区域表示滑雪场,区域中每个点都有对应的高度值,滑雪者只能从一个点滑向其上下左右四个相邻且高度更低的点,目标是找出在这个区域中最长的可滑行滑坡长度(即经过的点数最多的滑行路径)。
我们可以定义一个二维数组dp[i][j]
来表示状态,其中i
表示所在行的索引(取值范围是从 0 到 R - 1,R 为行数),j
表示所在列的索引(取值范围是从 0 到 C - 1,C 为列数)。dp[i][j]
的值代表从坐标为(i, j)
的这个点出发,所能达到的最长滑行路径长度(也就是能经过的最多点数)。状态转移方程推导
对于状态dp[i][j]
,我们需要考虑从它的四个相邻位置(上、下、左、右)转移过来的情况,来推导出状态转移方程:设当前点坐标为(i, j)
,高度为height[i][j]
,四个方向的偏移量可以用数组表示为int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
(分别对应上、下、左、右方向)。
对于每个方向k
(k 取值为 0 到 3):先计算出相邻位置的坐标,设相邻位置坐标为(new_i, new_j)
,其中new_i = i + dirs[k][0]
,new_j = j + dirs[k][1]
。接着判断相邻位置是否在滑雪场区域范围内(即0 <= new_i < R
且0 <= new_j < C
),并且该相邻位置的高度要小于当前位置高度(即height[new_i][new_j] < height[i][j]
)。如果满足上述条件,说明可以从相邻位置滑到当前位置(i, j)
,此时dp[i][j]
就可以尝试从dp[new_i][new_j]
的基础上转移过来,更新dp[i][j]
的状态值为:dp[i][j] = max(dp[i][j], dp[new_i][new_j] + 1)
。这里加 1 是因为要算上当前位置(i, j)
这一点,也就是从相邻位置滑过来后路径长度要加 1。如果遍历完四个方向后,dp[i][j]
还是初始值(通常初始化为 0),说明从这个位置出发没有可以滑行的相邻位置,那么dp[i][j]
就为 1(自身算一个点,长度为 1)。初始化
初始化dp
数组时,将所有元素都初始化为 0,因为一开始还没有计算各个位置的最长滑行路径长度,都处于未知状态:
vector<vector<int>> dp(R, vector<int>(C, 0));
#include <iostream>
// #include <cstring>
const int MAXN = 1005;
int row, col, maxLength;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
int arrayMatrix[MAXN][MAXN];
int dpMatrix[MAXN][MAXN];
// 简化后的坐标合法性检查函数
bool isInRange(int x, int y) {
return x >= 1 && x <= row && y >= 1 && y <= col;
}
int solve(int a, int b) {
if (dpMatrix[a][b]) return dpMatrix[a][b];
int res = 1;
for (int i = 0; i < 4; i++) {
int newX = a + dx[i];
int newY = b + dy[i];
if (isInRange(newX, newY) && arrayMatrix[newX][newY] < arrayMatrix[a][b])
res = std::max(res, solve(newX, newY) + 1);
}
return dpMatrix[a][b] = res;
}
int main() {
std::cin >> row >> col;
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= col; j++) {
std::cin >> arrayMatrix[i][j];
dpMatrix[i][j] = 0; // 初始化dp数组
}
}
maxLength = 0;
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= col; j++) {
maxLength = std::max(maxLength, solve(i, j));
}
}
std::cout << maxLength << std::endl;
return 0;
}