这道题是一道比较基础的dp问题, 最开始我用成Dfs来写, 不出意外果然超时了
定义这道题的状态dp[i][j]为 : 从i行j列出发的最大滑行长度
状态转移方程应该就是: dp[i][j] = max(dp[i][j], dp[i-1][j] | h[i][j] > h[i-1][j]), max(dp[i][j], dp[i+1][j] | h[i][j] > h[i+1][j]),
max(dp[i][j], dp[i][j-1] | h[i][j] > h[i][j-1]),max(dp[i][j], dp[i][j+1] | h[i][j] > h[i][j+1])
然后牵扯到一个顺序问题, 这道题目不能直观的从前到后或从后到前, 需要对高度进行从小到大排序, 再依次遍历
同时注意初始化问题和边界问题, 各点初始化为1, 同时注意对越界情况的判断
//滑雪
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn = 110, maxh = 10010;
int R, C;
int dp[maxn][maxn]; //从i行j列出发的最大长度
int height[maxn][maxn]; //高度
struct Point{
int x, y, h; //坐标和高度;
}s[maxn*maxn];
bool cmp(Point a, Point b){
return a.h < b.h; //按高度从小到大排序
}
int solve()
{
for(int i = 0; i <= R+1; i++)
for(int j = 0; j <= C+1; j++)
dp[i][j] = 1; //初始化为1
sort(s+1, s+R*C+1, cmp);
for(int i = 1; i <= R*C; i++){
if(s[i].x+1<=R && height[s[i].x][s[i].y] > height[s[i].x+1][s[i].y])
dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x+1][s[i].y]+1); //切记只有选了才+1
if(s[i].x-1>0 && height[s[i].x][s[i].y] > height[s[i].x-1][s[i].y])
dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x-1][s[i].y]+1);
if(s[i].y+1<=C && height[s[i].x][s[i].y] > height[s[i].x][s[i].y+1])
dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x][s[i].y+1]+1);
if(s[i].y-1>0 && height[s[i].x][s[i].y] > height[s[i].x][s[i].y-1])
dp[s[i].x][s[i].y] = max(dp[s[i].x][s[i].y], dp[s[i].x][s[i].y-1]+1);
}
int ans = 0;
for(int i = 1; i <= R; i++)
for(int j = 1; j <= C; j++)
ans = max(ans, dp[i][j]);
return ans;
}
int main()
{
cin >> R >> C;
int no = 1;
for(int i = 1; i <= R; i++)
for(int j = 1; j <= C; j++){
cin >> height[i][j];
s[no].x = i, s[no].y = j, s[no].h = height[i][j];
no++;
}
cout << solve() << endl;
return 0;
}