一、问题描述
滑雪中,为了获得速度,滑的区域必须向下倾斜,现在想知道一个区域中的最长滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅
16 17 18 19 6 当高度减小。在上面的例子中,一条可滑行的滑坡为:
15 24 25 20 7 24-17-16-1。当然25-24-23-...-3-2-1更长。
14 23 22 21 8 事实上,这是最长的一条。
13 12 11 10 9
输入:
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
输出:
输出最长区域的长度。
二、解题思路
定义m[i][j]表示从点(i,j)为起点滑行的最大长度。滑行时,选择周围可以滑行的且m值最大的方向滑行。如果(i,j)的四个相邻元素都存在的话,则可以得到如下递归式(如图1):
m[i][j]=Max(m[i][j-1],m[i][j+1],m[i-1][j],m[i+1][j]) +1
通过递归地计算m[i][j-1],m[i][j+1],m[i-1][j]和m[i+1][j]的值,找中四个中最大的一个,即是下一步滑行的位置,以此递归,直到不能继续滑行时返回。求解过程中,每求解到一个点的最大滑行长度则保存在数组m[i][j]中,因此不会重复求解同一个点的最大滑行长度。
用两重循环搜索整个矩阵中m[i][j]最大的点,m[i][j]就是要求解的最长区域的长度。
|
|
i-1,j
|
|
|
i,j-1
|
i,j
|
i,j+1
|
|
|
i+1,j
|
|
图1
三、算法效率
时间复杂度0(n2),空间复杂度0(n2)。
四、源代码
1
#include <iostream>
2
using namespace std;
3
int h[101][101];
4
int m[101][101];
5
int r,c;
6
int GetHigh(int i,int j)
7

{
8
9
if(m[i][j]!=-1)
10
return m[i][j];
11
else
12
{
13
int max=0;
14
int temp;
15
if(j>1)
16
{
17
if(h[i][j]>h[i][j-1])
18
{
19
temp=GetHigh(i,j-1);
20
if(max<temp)
21
max=temp;
22
}
23
}
24
if(j<c)
25
{
26
if(h[i][j]>h[i][j+1])
27
{
28
temp=GetHigh(i,j+1);
29
if(max<temp)
30
max=temp;
31
}
32
}
33
if(i>1)
34
{
35
if(h[i][j]>h[i-1][j])
36
{
37
temp=GetHigh(i-1,j);
38
if(max<temp)
39
max=temp;
40
}
41
}
42
if(i<r)
43
{
44
if(h[i][j]>h[i+1][j])
45
{
46
temp=GetHigh(i+1,j);
47
if(max<temp)
48
max=temp;
49
}
50
}
51
m[i][j]=max+1;
52
return m[i][j];
53
}
54
55
}
56
int main()
57

{
58
int i,j;
59
int Max=-1;
60
int temp;
61
cin>>r>>c;
62
for(i=1;i<=r;i++)
63
for(j=1;j<=c;j++)
64
cin>>h[i][j];
65
for(i=1;i<=r;i++)
66
for(j=1;j<=c;j++)
67
m[i][j]=-1;
68
for(i=1;i<=r;i++)
69
{
70
for(j=1;j<=c;j++)
71
{
72
temp=GetHigh(i,j);
73
if(Max<temp)
74
Max=temp;
75
}
76
}
77
cout<<Max<<endl;
78
return 1;
79
80
81
}