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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM