滑雪

滑雪

Problem 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 <= 1000)。下面是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

解释:

一道搜索题,找一条最长的路,我最先一开始想的是,从一个点出发,如果它可以去下一个点,那么我就判断一下是不是可以进行更新其最长的距离,然后再去找下一个点,然后记录当前的最长路径,以方便剪枝。然后就是超内存,超时,运行错误,各种问题。发现自己搞不定,想不到一个解决办法,按照我之前的思路写下去,于是百度。

对于一个点而言它的最长距离,肯定是从它的四个方向过来的。一次类推,假设一个点是有左边的点更新的,左边的点又是由左边的过来的,一直推下去,当一个点的最短距离确定时,就已经可以确定所有与它有关的,包括间接的点了,并且每一个点都需要需要判断一次,而不再是重复计算了。采用后更新的方式。就是在递归的归过程中更新。这样可以避免许多不必要的循环。

自己还是习惯于在递的过程中更新,在归的过程中去恢复状态,这次学到了,在归的过程中去更新,可以省很多事。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 const int N  = 2110;
 5 const int INF = 1314520;
 6 struct point {
 7   int height;
 8   int max_lenght;
 9 }ski_map[N][N];
10 
11 int R, C;
12 int max_res;
13 
14 int dir[][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
15 
16 int Scan() { //输入外挂
17   int res = 0, ch, flag = 0;
18   if ((ch = getchar()) == '-')
19     flag = 1;
20   else if (ch >= '0' && ch <= '9')
21     res = ch - '0';
22   while ((ch = getchar()) >= '0' && ch <= '9')
23     res = res * 10 + ch - '0';
24   return flag ? -res : res;
25 }
26 
27 void init() {   // 初始化, 在R*C的地图上面有一个方框包裹起来
28   for (int i = 0; i <= R+2; i++) {
29     ski_map[i][0].height = ski_map[i][C+1].height = INF;
30   }
31 
32   for (int i = 0; i <= C+2; i++) {
33     ski_map[0][i].height = ski_map[R+1][i].height = INF;
34   }
35 }
36 
37 int search (int x, int y) {
38   int max_len = 0, len = 0;
39   ski_map[x][y].max_lenght = 1;
40 
41   for (int i = 0; i < 4; i++) {
42     int tx = x + dir[i][0];
43     int ty = y + dir[i][1];
44     if (tx <= 0 || tx > R || ty <= 0 || ty > C) continue;
45     if (ski_map[x][y].height > ski_map[tx][ty].height) {  //   表示这个(x, y)可以滑到 (tx, ty) 位置去
46       if (ski_map[tx][ty].max_lenght == 0) {  //  表示(tx,ty)这个位置,还没有被滑到过,如果滑到了,当前最大滑行距离就是上一次的滑行距离。
47         len = search(tx, ty);
48       } else {
49         len = ski_map[tx][ty].max_lenght;
50       }
51       max_len = max(len, max_len);
52     } 
53 
54    
55   }
56   return ski_map[x][y].max_lenght += max_len; //   从四个方向中选择最大一个滑行距离
57 }
58 
59 int main () {
60 
61   while (~scanf("%d %d", &R, &C)) {
62     max_res = 0;
63     init();
64     for (int i = 1; i <= R; i++) { //  读入数据
65       for (int j = 1; j <= C; j++) {
66        ski_map[i][j].height = Scan();
67        ski_map[i][j].max_lenght = 0;
68         
69       }
70     } 
71 
72     for (int i = 1; i <= R; i++) { //遍历每一个点,采用后更新
73       for (int j = 1; j <= C; j++) {
74         if (ski_map[i][j].max_lenght == 0) {
75           int len = search(i, j);
76           max_res = max(max_res, len);
77         }
78       }
79     }
80 
81     printf("%d\n", max_res);
82   }
83   return 0;
84 }
View Code

 

转载于:https://www.cnblogs.com/gznb/p/11211859.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值