搜索入门问题---滑雪

滑雪的确很刺激,可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。现想知道在一个区域中最长的滑坡。

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

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更长。事实上,这是最长的一条。
输入:
每组数据的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。输入以EOF结束
输出:
输出最长区域的长度。
限制:时间3s 内存64MB
题目分析:
从题目看不难联想到应该使用搜索算法,但是在这种边界不明确的搜索中常规的遍历搜索是必然会超时的,就涉及对其的优化,
因为此题中终点并不确定,所以常用的剪枝思路也不一定行得通,那么我们的思路就应该放在如何减少每条路径的运算时间。
根据题意不难发现,每个点对应的最长下滑路径是固定的,对于访问的每个点我们都可以记录下这个点滑到低端时的路径长度,
在新路径遍历到时直接加上这一段最长路径即可,避免了每个结点的多方向试探同时减少了重复的运算量。
代码实现(C++):

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 using namespace std;
 6 int m,n;                                    //声明两个变量做完滑雪场边界
 7 int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};               //声明方向数组
 8 int vis[101][101];                              //记录每个点的最长路径
 9 int smap[101][101];                             //记录滑雪地图
10 int dfs(int x,int y)                              //搜索函数
11 {
12         for(int i=0; i<4; i++)                        //遍历四个方向
13         {
14             int xx=x+dir[i][0];
15             int yy=y+dir[i][1];
16             if(xx>=0&&yy>=0&&xx<m&&yy<n&&smap[xx][yy]<smap[x][y])  //判断是否到了终点(边界或者周围没有更低点)
17             {
18                 if(vis[xx][yy])                      //判断移动后的点是否已有记录
19                     vis[x][y]=max(vis[x][y],vis[xx][yy]+1);      //vis[x][y]在此函数中表示已经获取到的vis[x][y]的最大值,如果是第一个方向就是0,否则为已经搜索过的方向中最长的路径
20                 else  
21                     vis[x][y]=max(vis[x][y],dfs(xx,yy)+1);      //如果下一个点没有访问过则搜索出它的最长路径并与前几次访问方向获得的最长路径比较
22             }
23         }
24     return vis[x][y];                             //返回vis[x][y]的值,经过如上处理vis[x][y]应该为所有方向里最长的一条
25 }
26 int main()
27 {
28     while(scanf("%d %d",&m,&n)!=EOF)                    
29     {
30         memset(vis,0,sizeof(vis));                      //初始化路径记录
31         for(int i1=0; i1<m; i1++)
32             for(int i2=0; i2<n; i2++)
33                 scanf("%d",&smap[i1][i2]);                  //在这里录入地图
34         int smax=0;                                //使用一个变量储存遍历过程中路径的最大值
35         for(int i1=0; i1<m; i1++)
36             for(int i2=0; i2<n; i2++)
37                 if(vis[i1][i2])                          //遍历全图寻找最长的路径,已经有储存(遍历过程中之前访问的结点经过了现在遍历到的结点)则直接smax储存比储存值更大的路径长度
38                     smax=max(smax,vis[i1][i2]);
39                 else
40                     smax=max(smax,dfs(i1,i2));                  //对未访问过的点进行搜索
41         printf("%d\n",smax+1);                            //根据题意输出值应比获得的最长路径大1
42     }
43     return 0;
44 }


猜你喜欢

转载自www.cnblogs.com/Deach/p/10036048.html