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。
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
Output
扫描二维码关注公众号,回复:
4081091 查看本文章
输出最长区域的长度。
25
这个题目我的思路很简单,就是对每一个点进行深度搜索,得到每一个点的最大路径,然后取出所有最大路径。但要注意的是,为了避免重复搜索,所以需要定义一个count二维数组,来记下已经搜索过的结果。
下面是我自己写的代码:
#include <iostream>
#include<cstdio>
#include <time.h>
#include <cstring>
int h[100][100]={0}; ////高度图
int count[100][100]={0}; ///记录每一个高点的最大滑雪长度
int f[][2]={{1,0},{0,1},{-1,0},{0,-1}}; ///这个在注释的代码有用,在做dfs的时候用这个,整个的dfs会显得简洁
int r,c;
int max_line = 0;
int find(int i,int j)
{
int max_t=0;
if(count[i][j]>0)
return count[i][j];
/////up search
if(i-1>=0)
{
if(h[i-1][j]<h[i][j])
{
max_t = std::max(find(i-1,j),max_t);
}
}
/////down search
if(i+1<r)
{
if(h[i+1][j]<h[i][j])
{
max_t = std::max(find(i+1,j),max_t);
}
}
////left search
if(j-1>=0)
{
if(h[i][j-1]<h[i][j])
max_t = std::max(find(i,j-1),max_t);
}
//////right search
if(j+1<c)
{
if(h[i][j+1]<h[i][j])
{
max_t = std::max(find(i,j+1),max_t);
}
}
///如果用下面的代码,那么这个函数以上四个遍历都可以注释掉了,这个是我参考网友的写法写的比较简洁,但思路一样,并不影响速度
// for ( int z = 0 ; z < 4 ; z ++ )
// {
// int s = i + f[z][0] ;
// int t = j + f[z][1] ;
// if ( s < 0 || t < 0 || s >= r || t >= c )
// continue;
// if ( h[s][t] >= h[i][j] )
// continue;
// max_t = std::max ( max_t , find ( s , t ) ) ;
// }
count[i][j]=max_t+1; /////关键步骤,记下每一次深度搜索的结果,避免重复搜索
return max_t+1; /////如以上没有一个满足条件,就可以直接+1,由于递归,所以只要是经过的点都+1,刚好记录下深度信息
}
int main() {
memset( count , -1 , sizeof ( count ) );
scanf("%d%d", &r, &c); ////scanf 是以回车一下作为输入数据的间隔
printf("input h data");
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
{
scanf("%d", &h[i][j]);
// h[i][j]=i+j;
}
clock_t start=clock();
int ans = 0;
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
{
count[i][j]=find(i,j);
ans = std::max(ans, count[i][j]);
}
clock_t end=clock();
std::cout<<"cost time :"<<double(end-start)/CLOCKS_PER_SEC*1000 <<"s"<<std::endl;
printf("%d", ans);
return 0;
}
该算法主要的思路就是记忆搜索,此算法在计算100*100的数组时,只需要1.394s完成计算,如果不采用记忆的话,算法直接卡死。