题意:给你一个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;
    }
}