POJ-1088 滑雪 (包含部分自用测试数据)

这题最简单的想法是深搜+记录,由于数据量比较小。这么做可以AC。如果在h大的情况下这种递归方法总会有一些问题。

如果转换一下,这个可以使用递推来解决,先对高度进行由低到高的排序,然后顺序对这些高度计算路径长度,可以通过数学归纳法证明此方法的合理性:

1、首先我们来考虑:一个高度如果是最小,那么由它开始的最长路径必然是1。因为它只能走到自己。

2、那么考虑高度第二小的值,首先它只比最小的那个高,那我们可以得出结论,如果它周围有最小的那个值,那么由它开始的路径长度是2,如果周围没有比它小的,那么路径长度为1。

假设N=m时,所有等于m或者比m小的高度都计算完最长路径,所有比m大的都还未被计算。那么当N=m+1时,记此高度的坐标为row,column,计算完的最长路径存放在way[r][c]中(way[i][j]初始值为-1)。

则way[row-1][column], way[row+1][column], way[row][column-1], way[row][column+1]4个相邻节点中,如果有way[x][y] + 1 > way[row][column],那么说明此节点的高度<=m+1,判断高度,如果小于则可以从[row,column]滑到[x,y],如果way[x][y]==-1,那么说明[x,y]点大于或等于[row,column],即使以后计算得出结果,也不能从[row,column]滑到[x,y],所以对[row,column]节点来讲,当前计算的最远路径满足完备性。可以根据之前计算的前m个高度获得最优解结果。

所以伪代码如下:

for (int i = 0; i < r*c; i++){
  找到h[i]对应的坐标
  依次判断周围四个点的最长路径和高度
  得出当前坐标的结果
}

这种方式的复杂度是:排序阶段O(NlogN),计算阶段是O(4N),所以总的复杂度是O(NlogN),在这个计算方式下数据范围远不止10000。

 

 

几个测试数据:

2 3

1 2 3

4 5 6

 

3 3

6 6 6 

6 6 6 

6 6 6

 

1 5

3 2 4 3 2

想了想还是贴个深搜吧,毕竟简单。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 int a[102][102], way[102][102];
 5 int r, c;
 6 const int maxint = 1000001;
 7 
 8 int findway(int i, int j){
 9   if (way[i][j] > 0) return way[i][j];
10   if (a[i-1][j] < a[i][j])
11     if (findway(i-1,j)+1 > way[i][j])
12       way[i][j] = way[i-1][j]+1; 
13   if (a[i+1][j] < a[i][j])
14     if (findway(i+1,j)+1 > way[i][j])
15       way[i][j] = way[i+1][j]+1;
16   if (a[i][j-1] < a[i][j])
17     if (findway(i,j-1)+1 > way[i][j])
18       way[i][j] = way[i][j-1]+1;
19   if (a[i][j+1] < a[i][j])
20     if (findway(i,j+1)+1 > way[i][j])
21       way[i][j] = way[i][j+1]+1;
22   //printf("i=%d j=%d way=%d\n", i, j, way[i][j]);
23   return way[i][j];
24 }
25 
26 int main(){
27   int i, j, maxl;
28   maxl = 0;
29   scanf("%d %d", &r, &c);
30   for (i = 0; i <= r+1; i++)
31     for (j = 0; j <= c+1; j++)
32       a[i][j] = maxint;
33   for (i = 1; i <= r; i++)
34     for (j = 1; j <= c; j++){
35       scanf("%d", &a[i][j]);
36       way[i][j] = -1;
37     }
38   for (i = 1; i <=r; i++)
39     for (j = 1; j <= c; j++){
40       if ((a[i-1][j] >= a[i][j])&&(a[i+1][j] >= a[i][j])&&(a[i][j-1] >= a[i][j])&&(a[i][j+1] >= a[i][j]))
41         way[i][j] = 1;
42     }
43   for (i = 1; i <= r; i++)
44     for (j = 1; j <= c; j++){
45       if (maxl < findway(i, j)) maxl = way[i][j];
46     }
47   printf("%d\n", maxl);
48 }

 

posted @ 2016-02-18 18:52  月影舞华  阅读(2058)  评论(1编辑  收藏  举报