POJ 1088 滑雪 遞歸+dp | 拓撲排序

從每個點(i,j)向四個方向去看
如果某一個方向(a,b)的數值比當前位置小
先求解(a,b)的最長距離,之後加1即可
樸素的遞歸重複求解了很多子問題,我們每計算出一個子問題的解,便將他進行存儲,這樣就可以大大減少時間。

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int a[101][101];
int dp[101][101];
int R,C;

int findw(int i,int j){
    int ret = 1;
    if( i>=0 && i<R && j>=0 && j<C ){
        if( dp[i][j]>0 ){
            //直接調用子問題的解
            return dp[i][j];
        }
        if( i+1 < R && a[i][j] > a[i+1][j]){
            ret = max(ret,1+findw( i+1,j ) );
        }
        if( i-1 >=0 && a[i][j] > a[i-1][j]){
            ret = max(ret,1+findw( i-1,j ) );
        }
        if( j+1 < C && a[i][j] > a[i][j+1]){
            ret = max(ret,1+findw( i,j+1 ) );
        }
        if( j-1 >= 0 && a[i][j] > a[i][j-1]){
            ret = max(ret,1+ findw( i,j-1 ) );
        }
    }
    //記錄子問題的解
    dp[i][j] = ret;
    return ret;
}
int main()
{
    while(scanf("%d%d",&R,&C)!=EOF){
        memset(dp,0,sizeof(dp));
        int ret = -1;
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                ret = max(ret, findw(i,j));
            }
        }
        cout<<ret<<endl;
    }
    return 0;
}

在這裏插入圖片描述


拓撲排序:

在這裏插入圖片描述
先將二維數組遍歷一遍,每次統計上下左右四個位置中比當前位置(i,j)小的個數,這個爲(i,j)的度
將所有度爲0的點推入隊列

依次從隊列取出一個點,
更新該點周圍四個點的度,
計算周圍四個點的最大路徑長度,
記錄在dp數組裏面

直到隊列爲空
dp中的最大值就是最後的答案
但不是最後一個出隊的時候產生最大值!

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

int a[101][101];
int dp[101][101];
int du[101][101];
int R,C;

struct point{
    int x;
    int y;
    point():x(0),y(0){}
    point(int x,int y):x(x),y(y){}
};

int solve(){
    int ret = 0;
    queue<point> qu;
    for(int i=0;i<R;i++){
        for(int j=0;j<C;j++){

            if( i+1 < R && a[i][j] > a[i+1][j]){
                du[i][j]++;
            }
            if( i-1 >=0 && a[i][j] > a[i-1][j]){
                du[i][j]++;
            }
            if( j+1 < C && a[i][j] > a[i][j+1]){
                du[i][j]++;
            }
            if( j-1 >= 0 && a[i][j] > a[i][j-1]){
                du[i][j]++;
            }
            if( du[i][j] ==0 ){
                qu.push( point(i,j) );
            }
        }
    }
    /*
    for(int i=0;i<R;i++){
        for(int j=0;j<C;j++){
          cout<<du[i][j]<<" ";
        }
        cout<<endl;
    }
    */
    while( !qu.empty() ){
        //debug(qu.size())
        point p = qu.front();
        qu.pop();
        int i = p.x;
        int j = p.y;

        if( i+1 < R && a[i][j] < a[i+1][j]){
            dp[i+1][j] = max(dp[i+1][j] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i+1][j]);

            du[i+1][j]--;
            if(du[i+1][j]==0){
                qu.push(point(i+1,j));
            }
        }



        if( i-1 >=0 && a[i][j] < a[i-1][j]){
            dp[i-1][j] = max(dp[i-1][j] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i-1][j]);
            du[i-1][j]--;
            if(du[i-1][j]==0){
                qu.push(point(i-1,j));
            }
        }


        if( j+1 < C && a[i][j] < a[i][j+1]){
            dp[i][j+1] = max(dp[i][j+1] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i][j+1]);
            du[i][j+1]--;
            if(du[i][j+1]==0){
                qu.push(point(i,j+1));
            }
        }


        if( j-1 >= 0 && a[i][j] < a[i][j-1]){
            dp[i][j-1] = max(dp[i][j-1] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i][j-1]);
            du[i][j-1]--;
            if(du[i][j-1]==0){
                qu.push(point(i,j-1));
            }
        }


    }
    return ret+1;

}

int main()
{
    while(scanf("%d%d",&R,&C)!=EOF){
        if(R==0 || C==0){
            cout<<0<<endl;
            continue;
        }
        memset(dp,0,sizeof(dp));
        memset(du,0,sizeof(du));

        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                scanf("%d",&a[i][j]);
            }
        }
        int ret = solve();
        cout<<ret<<endl;
    }
    return 0;
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章