P1434 [SHOI2002] 滑雪(记忆化搜索 DAG)
P1434 [SHOI2002] 滑雪
题意
给你一个 \(n\times m\) 的矩阵 \(A\), \(A_{i,j}\) 代表 \((i , j)\) 这个地方的高度,你可以从任意一个地方出发,然后走到一个和这个地方四联通并且高度严格小于当前位置高度地方,求你可以走的最长路线长度。
思路
很容易看出这是个搜索问题,但是也很明显会对某些状态重复访问,指数级的复杂度是一定会TLE的。这个时候就可以加上一个记忆化,这样就能解决超时的问题了。为什么不用递推用搜索,因为题目中存在复杂的拓扑结构,也就是从高处滑向低处,如果要递推的话,还要排序,实现起来非常麻烦,没有必要。
实现
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int f[N][N], g[N][N];
int n, m;
int d[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool check(int x, int y)
{
if(x < 1 || y < 1 || x > n || y > m) return false;
return true;
}
int dfs(int x, int y)
{
if(f[x][y] != -1) return f[x][y];
f[x][y] = 1;
for(int i = 0; i < 4; i ++)
{
int xx = x + d[i][0], yy = y + d[i][1];
if(!check(xx, yy)) continue;
if(g[xx][yy] <= g[x][y]) continue;
f[x][y] = max(f[x][y], dfs(xx, yy) + 1);
}
return f[x][y];
}
int main()
{
memset(f, -1, sizeof f);
cin >> n >> m;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
cin >> g[i][j];
int res = 0;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
res = max(res, dfs(i, j));
cout << res << '\n';
}