FatMouse and Cheese(DP+記憶化搜索)

在這裏插入圖片描述
在這裏插入圖片描述
題意:給你一個N*N的的矩陣,要你找到一條最大的路徑,並且每次只能水平或者垂直的走不超過k步,並且下一步的值要大於上一步的值,要你輸出路徑的最大值。
思路:
這個題不太難想到dp[ i ][ j ]可以由四個方向轉移過來,但是這樣做不了。因爲無論你怎麼搞都會存在有些轉移本身就不是最優解,無法轉移過來。
這題需要用記憶化搜索思路和上面是一樣的,不過記憶化搜索會搜到一個點,當他的四個方向的值都比他小這時就是遞歸出口了,然後把它轉移出另外一個狀態,每次取四個方向的最大值即可。
狀態轉移方程:
在這裏插入圖片描述
不過這個不能用循環做,只能用搜索取做。因爲要找遞歸出口循環顯然不太適合。
總結:是個好題,思路不太難,但是傳統的循環不太適合,需要繼續多深入思考,找到滿足一個點都大於四個方向的值的這樣遞歸出口,還是比較由思維難度的。(畢竟dp從來都不是簡單題~)
代碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 10;
int a[maxn][maxn];
int dp[maxn][maxn];
int n,k;
int dir[][2]={{-1,0},{1,0},{0,-1},{0,1}};
int dfs(int x,int y){
    int M = 0;
    if(dp[x][y] != -1)return dp[x][y];
    for(int i = 1; i <= k; i++){
        for(int j = 0; j < 4; j++){
            int fx = x + i * dir[j][0];
            int fy = y + i * dir[j][1];
            if(fx < 1 || fy < 1 ||fy > n || fx > n)continue;
            if(a[x][y] < a[fx][fy]){
                int temp = dfs(fx,fy) ;
                M = max(M,temp);
            }
        }
    }
    return (dp[x][y] = M + a[x][y]);
}
int main(){
    while(scanf("%d%d",&n,&k)!=EOF){
        if(n == -1 && k == -1)break;
        memset(dp,-1,sizeof(dp));
        for(int i = 1 ; i <= n; i++){
            for(int j = 1; j <= n; j++){
                cin>>a[i][j];
            }
        }
        cout<<dfs(1,1)<<endl;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章