把格子按高度升序作为拓扑序,迭代填表求最长严格递减路径。
OJ: roj
题目 ID: 1280
难度:普及-
标签:普及-动态规划记忆化搜索DAGpython
创建: 2026-09-30 03:02
更新: 2026-10-05 07:50
题目描述
给定
输入:第一行
输出:一个整数,最长滑坡长度。
样例输入:
text
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样例输出:
text
25思路
设
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-07-05 21:47
# update_at: 2026-07-05 21:47
import sys
DIRS = ((-1, 0), (1, 0), (0, -1), (0, 1)) # 上下左右四个相邻方向
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
R, C = next(data), next(data)
grid = [[next(data) for _ in range(C)] for _ in range(R)]
# 按高度从小到大处理:算 (r,c) 时,比它低的邻格必然已算完,
# 等价于记忆化 dfs,但不需要递归(最长滑坡可达 R*C 级深度)。
length: dict[tuple[int, int], int] = {} # (r,c) -> 从该格出发的最长滑坡
for h, r, c in sorted((grid[r][c], r, c) for r in range(R) for c in range(C)):
lower = ( # 所有比当前格低、且在边界内的相邻格
length[(r + dr, c + dc)]
for dr, dc in DIRS
if 0 <= r + dr < R and 0 <= c + dc < C and grid[r + dr][c + dc] < h
)
length[(r, c)] = 1 + max(lower, default=0) # 一步都不滑也算了自身
print(max(length.values()))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 07:50
* update_at: 2026-10-05 07:50
*/
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 105;
int r, c;
int h[MAXN][MAXN]; // 每个格子的高度
int f[MAXN][MAXN]; // 从该格子出发的最长滑坡长度
int dr[4] = {-1, 1, 0, 0}; // 上下左右四个方向
int dc[4] = {0, 0, -1, 1};
struct Node {
int h, x, y;
} nodes[MAXN * MAXN];
// 按高度升序排序,得到拓扑序
bool cmp(Node a, Node b) {
return a.h < b.h;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> r >> c;
int cnt = 0;
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
cin >> h[i][j];
cnt++;
nodes[cnt].h = h[i][j];
nodes[cnt].x = i;
nodes[cnt].y = j;
}
}
sort(nodes + 1, nodes + cnt + 1, cmp);
int ans = 0;
for (int k = 1; k <= cnt; k++) {
int x = nodes[k].x;
int y = nodes[k].y;
f[x][y] = 1; // 至少包含自己
for (int d = 0; d < 4; d++) {
int nx = x + dr[d];
int ny = y + dc[d];
if (nx >= 1 && nx <= r && ny >= 1 && ny <= c && h[nx][ny] < h[x][y]) {
// 邻居更低,且已经处理过(因为按高度升序)
if (f[nx][ny] + 1 > f[x][y]) {
f[x][y] = f[nx][ny] + 1;
}
}
}
if (f[x][y] > ans) ans = f[x][y];
}
cout << ans << endl;
return 0;
}