P1434 [SHOI2002]滑雪

题目描述
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
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-ldots…-33-22-11 更长。事实上,这是最长的一条。

输入格式
输入的第一行为表示区域的二维数组的行数 RR 和列数 CC。下面是 RR 行,每行有 CC 个数,代表高度(两个数字之间用 11 个空格间隔)。

输出格式
输出区域中最长滑坡的长度。

该题直接用dfs会tle,所以我们运行记忆化搜索,dp[i][j]表示从第i行第j列能够滑的最大值的位置。如果在上一次dp[i][j]已经被求出,可以直接使用了。

include<bits/stdc++.h>

using namespace std;
int r,c;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0}; //表示四个方向
int a[101][101],dp[101][101];
int dfs(int x,int y);
int main()
{
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
scanf("%d",&a[i][j]);
int ans=0;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
ans=max(ans,dfs(i,j));
printf("%d ",ans);
}
int dfs(int x,int y)
{
if(dp[x][y]) return dp[x][y]; //如果dp[x][y]已经有值的时候,那么直接返回
dp[x][y]=1; //表示从上一个滑到该地方的长度为1
for(int i=0;i<4;i++)
{
int nowx=x+dx[i];
int nowy=y+dy[i];
if(nowx>=1&&nowx<=r&&nowy>=1&&nowy<=c&&a[x][y]>a[nowx][nowy])
dp[x][y]=max(dp[x][y],dfs(nowx,nowy)+1); //看四个方向哪个位置是最大值
}
return dp[x][y];
}

原文地址:https://www.cnblogs.com/zh1014/p/13419621.html