1. 程式人生 > >leetcode第一題:滑雪問題

leetcode第一題:滑雪問題

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完成計算,如果不採用記憶的話,演算法直接卡死。