滑雪
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
这道题目是一道递归问题,对每个“点”而言,其有前、后、左、右四个方向,看起来,它的时间复杂度好像是O(4^(R*C)),这好像是一个比汉罗塔复杂度更好的问题。实则不然,因为对每个“点”只需要做一次搜索即可。在搜索到某“点”后,用Len[i][j]((i,j)表示该“点”的位置)存储下该“点”的可滑行深度,即从该“点”出发的可滑行深度,并用bflag[i][j]=false来表明该“点”已被搜索,但下次再搜索到该“点”是,直接使用其可滑行深度Len[i][j]即可。因此,其时间复杂度为O(R*C)。具体实现如下:
#include "iostream"
using namespace std;
const int N = 101;
int itg[N][N];
int Len[N][N];
bool bflag[N][N];
int Search(int r, int c, int R, int C)
{
int dirct[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
int i, max = 1, itmp;
if(!bflag[r][c]) return Len[r][c];
for(i = 0; i < 4; i++)
{
if(r+dirct[i][0] >= 0 && r+dirct[i][0] < R && c+dirct[i][1] >= 0 && c+dirct[i][1] < C)
{
if(itg[r][c] > itg[r+dirct[i][0]][c+dirct[i][1]])
{
if(!bflag[r+dirct[i][0]][c+dirct[i][1]]) itmp = Len[r+dirct[i][0]][c+dirct[i][1]] + 1;
else itmp = Search(r+dirct[i][0], c+dirct[i][1], R, C) + 1;
if(max < itmp) max = itmp;
}
}
}
bflag[r][c] = false;
if(max > Len[r][c]) Len[r][c] = max;
return Len[r][c];
}
int LongestLen(int R, int C)
{
int max = 1;
int i, j;
for(i = 0; i < R; i ++)
{
for(j = 0; j < C; j ++)
{
Search(i, j, R, C);
if(max < Len[i][j]) max = Len[i][j];
}
}
return max;
}
int main(void)
{
int R, C;
int i, j;
cin >> R >> C;
for(i = 0; i < R; i++)
{
for(j = 0; j < C; j++)
{
cin >> itg[i][j];
Len[i][j] = 1;
bflag[i][j] = true;
}
}
cout << LongestLen(R, C) << endl;
return 0;
}
执行结果: