1. 程式人生 > >POJ DP 百練1088 滑雪問題

POJ DP 百練1088 滑雪問題

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更長。事實上,這是最長的一條。

分析:

明顯的dp問題。

dp[i][j] 表示的是以(i,j)為結尾的點的最高高度,

所以dp[i][j]的初始值為1,每次考慮點(i,j)的時候就看他上下左右的四個點,dp[i][j]就取那個高度比(i,j)低並且dp最大的那個點加1.

當然了,需要先排序,從h值最小的開始

PS:這裡面有一些邊界需要考慮,但是採用一些特殊的方法可以免去考慮邊界,具體做法參考程式碼

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

const int maxn = 105;
int a[maxn][maxn];
int dp[maxn][maxn];

struct node
{
    int x,y,h;
}A[maxn*maxn];

bool cmp(node a,node b)
{
    return a.h<b.h;
}

int main()
{
    int n,c;
    while(scanf("%d%d",&n,&c)==2)
    {

        memset(dp,0,sizeof(dp));
        memset(a,0,sizeof(a));
        int num = 0;
        for(int i = 1 ; i <= n ; i++)
        {
            for(int j = 1 ; j <= c ; j++)
            {
                scanf("%d",&a[i][j]);
                A[num].x=i;
                A[num].y=j;
                A[num++].h = a[i][j];
                dp[i][j] = 1 ;   //初始條件
            }
        }
        sort(A,A+num,cmp);//排序
        //這樣處理了之後就不用考慮邊界的問題了,邊界的點都比邊界外的高,但是邊界外面的dp初始值為0
        //加上1之後還是不變

        for(int k = 0 ; k < num ; k++)
        {
            int i = A[k].x;
            int j = A[k].y;
            if(a[i][j]>a[i-1][j]) dp[i][j] = max(dp[i][j],dp[i-1][j]+1);
            if(a[i][j]>a[i][j-1]) dp[i][j] = max(dp[i][j],dp[i][j-1]+1);
            if(a[i][j]>a[i+1][j]) dp[i][j] = max(dp[i][j],dp[i+1][j]+1);
            if(a[i][j]>a[i][j+1]) dp[i][j] = max(dp[i][j],dp[i][j+1]+1);
        }
        int ans = 0 ;
        for(int i = 1 ; i <= n ; i++)
        {
            for(int j = 1 ; j <= c ; j++)
            {
                //cout<<dp[i][j]<<" ";
                ans = max(ans,dp[i][j]);
            }
            //cout<<endl;
        }
        printf("%d\n",ans);
    }
    return 0;
}


/*
Auther:LIUYAN
2015.12.14
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
*/