滑雪
滑雪
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更长。事实上,这是最长的一条。
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 }