1. 程式人生 > >滑雪(動態規劃+dfs)

滑雪(動態規劃+dfs)

描述 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更長。事實上,這是最長的一條。 輸入 輸入的第一行表示區域的行數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
樣例輸出
25

題目大意

給出一個R*C的矩陣map[][],map[i][j]的值代表了第i行第j列這個點的高度,個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度減小。輸出滑行的最長的長度。

題目分析:動態規劃+深度搜索。記憶化搜尋每個點。

用dp[i][j]記錄從map[i][j]出發所能滑行的最長距離。狀態轉移方程:

dp[i][j] = max{ dp[i-1][j], dp[i+1][j],dp[i][j-1], dp[i][j+1] } + 1;

程式碼:

#include< stdio.h >
#define Max 105
#define max( a, b) ( a > b ? a : b )

int map[Max][Max];    //記錄每個點的高度
int dp[Max][Max];     //記錄從每個點出發能夠滑行的最長距離
int r, c;              //r和c分別表示行和列
int dir[4][2] = { { -1, 0 } , { 1, 0 } , { 0 , -1}, { 0, 1 } };  //上、下、左、右
int dfs( int x, int y){
    if(dp[x][y] > 1) return dp[x][y];  //如果已經計算過,直接返回
    int dx, dy;                       //也作為深搜的出口
    for( int I = 0; I < 4; i ++){            //尋找四個方位的最大長度
        dx = x + dir[i][0];
        dy = y + dir[i][1];
        if( dx < 0 || dx >= r || dy < 0 || dy  >= c) //如果座標超出邊界
            continue;
        if(map[dx][dy] < map[x][y])              //滿足滑雪條件
            dp[x][y] = max(dp[x][y], dfs(dx,dy) + 1);
    }
    return dp[x][y];   //返回最長滑行距離
}
int main(){
    int i, j;
    scanf("%d%d", &r, &c);
    for( I = 0; I < r; i ++){
        for(j = 0; j < c; j ++){
            scanf("%d", &map[i][j]);
            dp[i][j] = 1;   //每個點的最短距離是1
        }
    }
    int res = 0;
    for( i = 0; i < r; i ++){
        for(j = 0; j < c; j ++){
            res = max(res , dfs(i, j));
        }
    }
    printf("%d\n", res);
    return 0;
}