題意:給你一個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;
}
}