leetcode第一題:滑雪問題
阿新 • • 發佈:2018-11-15
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 <= 100)。下面是R行,每行有C個整數,代表高度h,0<=h<=10000。
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
Output
輸出最長區域的長度。
25
這個題目我的思路很簡單,就是對每一個點進行深度搜索,得到每一個點的最大路徑,然後取出所有最大路徑。但要注意的是,為了避免重複搜尋,所以需要定義一個count二維陣列,來記下已經搜尋過的結果。
下面是我自己寫的程式碼:
#include <iostream> #include<cstdio> #include <time.h> #include <cstring> int h[100][100]={0}; ////高度圖 int count[100][100]={0}; ///記錄每一個高點的最大滑雪長度 int f[][2]={{1,0},{0,1},{-1,0},{0,-1}}; ///這個在註釋的程式碼有用,在做dfs的時候用這個,整個的dfs會顯得簡潔 int r,c; int max_line = 0; int find(int i,int j) { int max_t=0; if(count[i][j]>0) return count[i][j]; /////up search if(i-1>=0) { if(h[i-1][j]<h[i][j]) { max_t = std::max(find(i-1,j),max_t); } } /////down search if(i+1<r) { if(h[i+1][j]<h[i][j]) { max_t = std::max(find(i+1,j),max_t); } } ////left search if(j-1>=0) { if(h[i][j-1]<h[i][j]) max_t = std::max(find(i,j-1),max_t); } //////right search if(j+1<c) { if(h[i][j+1]<h[i][j]) { max_t = std::max(find(i,j+1),max_t); } } ///如果用下面的程式碼,那麼這個函式以上四個遍歷都可以註釋掉了,這個是我參考網友的寫法寫的比較簡潔,但思路一樣,並不影響速度 // for ( int z = 0 ; z < 4 ; z ++ ) // { // int s = i + f[z][0] ; // int t = j + f[z][1] ; // if ( s < 0 || t < 0 || s >= r || t >= c ) // continue; // if ( h[s][t] >= h[i][j] ) // continue; // max_t = std::max ( max_t , find ( s , t ) ) ; // } count[i][j]=max_t+1; /////關鍵步驟,記下每一次深度搜索的結果,避免重複搜尋 return max_t+1; /////如以上沒有一個滿足條件,就可以直接+1,由於遞迴,所以只要是經過的點都+1,剛好記錄下深度資訊 } int main() { memset( count , -1 , sizeof ( count ) ); scanf("%d%d", &r, &c); ////scanf 是以回車一下作為輸入資料的間隔 printf("input h data"); for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { scanf("%d", &h[i][j]); // h[i][j]=i+j; } clock_t start=clock(); int ans = 0; for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) { count[i][j]=find(i,j); ans = std::max(ans, count[i][j]); } clock_t end=clock(); std::cout<<"cost time :"<<double(end-start)/CLOCKS_PER_SEC*1000 <<"s"<<std::endl; printf("%d", ans); return 0; }
該演算法主要的思路就是記憶搜尋,此演算法在計算100*100的陣列時,只需要1.394s完成計算,如果不採用記憶的話,演算法直接卡死。