Problem

顺治喜欢滑雪,这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待太监们来载你。顺治想知道载一个区域中最长的滑坡。

  区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

1
2
3
4
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

  顺治可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。

Input

输入的第一行表示区域的行数 R 和列数 C (1≤R,C≤500) 。下面是 R 行,每行有 C 个整数,代表高度 h,0≤h<103 。

Output

输出最长区域的长度。

EX

1
2
3
4
5
6
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
1
25

思路

很典型的深搜题,rc并不算大,O(n3)不会爆,所以直接dfs每个点的最长序列。注意要记忆化每个点的长度(在dfs内记忆化效果更优,因为能保存下更多点的mem值)。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include<iostream>
#include<cstdio>
using namespace std;

int ans = 0;
int r,c;
int height[502][502];
int mem[502][502] = {0};
int changex[4] = {-1, 1, 0, 0};
int changey[4] = {0, 0, -1, 1};

int dfs(int x, int y){
if(mem[x][y]){
return mem[x][y];
}
int maxx = 0;
for(int i = 0;i < 4;i++){
int xx = x + changex[i];
int yy = y + changey[i];
int hh = 0;
if(height[xx][yy] < height[x][y]){
hh = dfs(xx,yy);
}
hh++;
if(hh > maxx){
maxx = hh;
}
}
mem[x][y] = maxx;
return maxx;
}

int main(){
cin>>r>>c;
for(int i = 0;i <= r + 1;i++){
for(int j = 0;j <= c + 1;j++){
height[i][j] = 0x3f3f3f3f;
mem[i][j] = 0;
}
}
for(int i = 1;i <= r;i++){
for(int j = 1;j <= c;j++){
cin>>height[i][j];
}
}
for(int i = 1;i <= r;i++){
for(int j = 1;j <= c;j++){
int h = dfs(i,j);
if(h > ans){
ans = h;
}
}
}
cout<<ans<<endl;
return 0;
}