再谈记忆化搜索 HDU-1078

最近做DP题目,发现无论是LCS,还是有些题目涉及将动态规划的路径打印出来,而且有时候还要按格式输出,这个时候,记忆化搜索显得尤其重要,确实,记忆化搜索使用优化版本的动态规划,用起来思路清晰,非常方便

这个题目就是一个n*n的图里,从起点出发,只能横向或者纵向走最多k步,而且每次下个点都要比当前点的值要高,这样最终走完获得的总点权值最大是多少

明显的是一BFS 或者DFS,当然,我们稍微优化下,用记忆化搜索,就会成为很优化版本的DFS。

所以从代码看,这样的记忆化搜索,其实是从起点出发,但是最终要搜到最后一点,然后层层返回,此时,每个得到了返回值的点都已经是最优点了,所以下次再搜到这个点直接返回,这里节省了大量的时间与空间。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int G[105][105];
int dp[105][105];
int n,k;
int dir[][2]={{0,1},{1,0},{0,-1},{-1,0}};
int search(int x,int y)
{
    if (dp[x][y]>=0) return dp[x][y]; //如果已经得到最优解了,则直接返回。
    int maxn=0,temp=0;
    for (int q=1;q<=k;q++)
    {
        int nx,ny;
        for (int w=0;w<4;w++)
        {
            nx=x+q*dir[w][0];
            ny=y+q*dir[w][1];
            if (nx<0||ny<0||nx>=n||ny>=n) continue;
            if (G[nx][ny]<=G[x][y]) continue;
            temp=search(nx,ny);
            if (temp>maxn) maxn=temp; //求得接下来步骤的最优解,再返回上去。
        }
    }
    return dp[x][y]=G[x][y]+maxn;
}
int main()
{

    while (scanf("%d%d",&n,&k))
    {
        if (n==-1 && k==-1) break;
        int i,j,k;
        for (i=0;i<n;i++){
            for (j=0;j<n;j++){
                scanf("%d",&G[i][j]);
            }
        }
        memset(dp,-1,sizeof dp);
        //dp[0][0]=G[0][0];

        printf("%d
",search(0,0));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kkrisen/p/3369966.html