HDU 1078 FatMouse and Cheese(dp+记忆化搜索)史上最详细题解

来源:互联网 发布:朱苏力 知乎 编辑:程序博客网 时间:2024/05/29 13:42

题意:给定一幅图,每个点有一定权值,现在有一只老鼠在起始点(0,0),他能水平或者垂直移动1~k格之后,停在某点并获得权值,而且每次移动后所在的点,都要比刚离开的那个点的权值更大,求最多能获得多少权值。

思路:第一次做记忆化搜索题目,一开始用纯dp做的,找出了所谓状态转移方程,连样例都过不了,一直debug,还以为是哪里写错了,百度了一发,知道了原来要用记忆化搜索,顿时豁然开朗,也知道了为什么纯dp不对,原来,记忆化搜索还是搜索,从一条路通到底那种,通许多次而已,而dp只是找每个i,j所代表的最大的权值,他的顺序是死的,只是从两个for循环按部就班的找,所以他的路径是死的,一开始这题跟hdu2571一样,那题只能是往有往下走,不能回头,而这题,是四个方向都可以走,是一个“搜索”,所以要用记忆化搜索。

记忆化搜索:这里的dp代表的是从后来所有点一路走来的最大权值,先不断递归,走到不能走了,就要返回,返回值是 dp[x][y]+a[x][y],然后回到上一层递归,继续for循环,再到走不动。。。。然后取max的最大值,这时候dp【x】【y】就已经是最优解了,以后遇到他直接返回就行;回溯完了dp【0】【0】就是从0,0走的最大值;

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int maxn = 105;int dp[maxn][maxn], a[maxn][maxn],n,k, ans;int dir[4][2] = {1,0,0,1,-1,0,0,-1};int dfs(int x, int y){    if(dp[x][y])        return dp[x][y];    int ans = 0;    for(int j = 1; j <= k; j++)    for(int i = 0; i < 4; i++)    {        int tx = x + j*dir[i][0];        int ty = y + j*dir[i][1];        if(tx < n && ty < n && tx >= 0 && ty >= 0 && a[tx][ty] > a[x][y])        {            ans = max(ans, dfs(tx,ty));// + a[x][y];        }    }    return dp[x][y] = ans + a[x][y];}int main(){    while(~scanf("%d%d",&n,&k))    {        if(n == -1 && k == -1) break;        for(int i = 0; i < n; i++)            for(int j = 0; j < n; j++)            scanf("%d",&a[i][j]);        memset(dp,0,sizeof(dp));        printf("%d\n",dfs(0,0));    }    return 0;}


1 0
原创粉丝点击