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 }