Description
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
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
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
Sample Output
25
Source
SHTSC 2002
题解:
第一:首先由题可知这题需要走的路程最长才是解,那么是否从最大的数开始走就能走的最大呢?答案是否定的。
第二:需要一个所有遍历,来遍历以任意元素为起点能走的最大路程,至于怎么从一堆最大数中找最最大的就很简单了。
第三:判断不要越界
第四:要知道每进行成功一个dfs路程数就应该加一,所以在递归的时候,用上max()函数使dfs的值加一后与当前位置上的dp值二者留一最大值。
第五:将第0行和第0列的全部都设为1,这样就不用考虑越界问题了。
第六:要知道当该位置上的数比四周的数小或等,路径开始返回,得出此次路程的总长。且dp记载的是每个位置上的最长路程。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int map[105][105];
int dp[105][105];
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int M(int a,int b)
{
return a>b?a:b;
}
int dfs(int i,int j)
{
int t,max=0,temp=0;
temp=map[i][j];
if(dp[i][j]!=0)return dp[i][j];
if(temp<=map[i][j+1]&&temp<=map[i][j-1]&&temp<=map[i+1][j]&&temp<=map[i-1][j])return 1;
for(t=0;t<4;t++)if(map[i+dir[t][0]][j+dir[t][1]]<map[i][j])max=M(dfs(i+dir[t][0],j+dir[t][1])+1,max);
return max;
}
int main()
{
memset(map,1,sizeof(map));
memset(dp,0,sizeof(dp));
int c,r,i,j,sum=0;
cin>>c>>r;
for(i=1;i<=c;i++)for(j=1;j<=r;j++)cin>>map[i][j];
for(i=1;i<=c;i++)for(j=1;j<=r;j++)dp[i][j]=M(dfs(i,j),dp[i][j]),dp[i][j];
for(i=1;i<=c;i++)for(j=1;j<=r;j++)sum=M(dp[i][j],sum);
cout<<sum<<endl;
return 0;
}