#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 310;
int n, m;
int h[N][N], f[N][N]; // h[][]每个点的高度
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int dp(int x, int y) {
int &v = f[x][y];
if (v != -1) return v; // v != -1表示已经算过了,直接返回即可
v = 1; //v初始化一下,v最小值是1(因为至少可以走当前格子)
for (int i = 0; i < 4; i ++) { //否则枚举 上下左右 四个格子,用--偏移量
int a = x + dx[i], b = y + dy[i];
if (a >= 1 && a <= n && b >= 1 && b <= m && h[x][y] > h[a][b]) //在界限内没有出边界 且 要走过的高度 < 当前的高度 这里h[x][y] > h[a][b]不能取等号,因为题目说只能走到低于自己目前高度
v = max(v, dp(a, b) + 1); // 这里是()不是dp[a][b]!!! 易写错 满足if条件,当前路径才能走到这个点
}
return v;
}
int main () {
cin >> n >> m;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
cin >> h[i][j];
memset(f, -1, sizeof f); //记忆化搜索的套路:先把所有状态初始化成-1,表示每个状态都没有被算过
int res = 0;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
res = max(res, dp(i, j)); //dp(i,j)返回的是(i,j)这个状态,是求出来(i,j)这个状态并且返回,不能直接写f[i][j],因为f[i][j]没有求出来呢!
cout << res << endl;
return 0;
}
下标从0开始的代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 310;
int n, m;
int h[N][N], f[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int dp(int x, int y) {
int &v = f[x][y];
if (v != -1) return v;
v = 1;
for (int i = 0; i < 4; i ++) {
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < n && b >= 0 && b < m && h[x][y] > h[a][b]) // !!!!下标从零开始的情况 a>=0不是a>=1了 a<n 不是a<=n
v = max(v, dp(a, b) + 1);
}
return v;
}
int main () {
cin >> n >> m;
for (int i = 0; i < n; i ++)
for (int j = 0; j < m; j ++)
cin >> h[i][j];
memset(f, -1, sizeof f);
int res = 0;
for (int i = 0; i < n; i ++)
for (int j = 0; j < m; j ++)
res = max(res, dp(i, j));
cout << res << endl;
return 0;
}