首页 > 代码库 > HDU--1078--FatMouse and Cheese--记忆化搜索

HDU--1078--FatMouse and Cheese--记忆化搜索

FatMouse and Cheese

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5128    Accepted Submission(s): 2078


Problem Description
FatMouse has stored some cheese in a city. The city can be considered as a square grid of dimension n: each grid location is labelled (p,q) where 0 <= p < n and 0 <= q < n. At each grid location Fatmouse has hid between 0 and 100 blocks of cheese in a hole. Now he‘s going to enjoy his favorite food.

FatMouse begins by standing at location (0,0). He eats up the cheese where he stands and then runs either horizontally or vertically to another location. The problem is that there is a super Cat named Top Killer sitting near his hole, so each time he can run at most k locations to get into the hole before being caught by Top Killer. What is worse -- after eating up the cheese at one location, FatMouse gets fatter. So in order to gain enough energy for his next run, he has to run to a location which have more blocks of cheese than those that were at the current hole.

Given n, k, and the number of blocks of cheese at each grid location, compute the maximum amount of cheese FatMouse can eat before being unable to move.
 

Input
There are several test cases. Each test case consists of

a line containing two integers between 1 and 100: n and k
n lines, each with n numbers: the first line contains the number of blocks of cheese at locations (0,0) (0,1) ... (0,n-1); the next line contains the number of blocks of cheese at locations (1,0), (1,1), ... (1,n-1), and so on.
The input ends with a pair of -1‘s.
 

Output
For each test case output in a line the single integer giving the number of blocks of cheese collected.
 

Sample Input
3 1 1 2 5 10 11 6 12 12 7 -1 -1
 

Sample Output
37

题意:老鼠初始时在nXn的矩阵的(0.0),每次最多向一个方向移动k格,每次移动过去的那个格子里面的数值必须比当前所在格子里面的大,求出路径上所有数值总和最大值

解析:

记忆化搜索,根据题意只好扩散性搜索,就是那种在一个点对于它能走到的所有点暴力搜索,这样会超时。

记忆化搜索是这样实现的:可以理解为结果的形成是反向的,从终点向起点(0,0)慢慢形成,每次搜索一个点周围能够满足条件的点,每找到一个点就继续递归找这个点周围满足条件的点,最终找到的点将会是数值最大的,也就是终点,这时把矩阵map中的数值记录起来当作所有用它当作终点的路径反向搜索的最大值,然后向上层返回这个值,而对于上一层的这个点来说,下面返回的就是下面那段路程的数值的最大值,于是将这个返回上来的值和这个点的数值加起来当作最大值。

我知道光说是不怎么会懂的,所以画了个图,方便大伙观摩,也为了以后复习的时候好看看,算做个笔记了。。



WA了一次,原因是写代码时听歌去了,没有考虑k

TLE了一次,原因是直接扩散性暴力搜索


#include <iostream>
#include <cstdio>
#include <cstring>
#define MM(a,b) a<b?b:a
using namespace std;
int n,m,map[111][111],sum[111][111],dd[4][2]={0,1,0,-1,1,0,-1,0};
int dfs(int X,int Y)
{
    int i,j,k,l=0,x,y;
    if(sum[X][Y])return sum[X][Y];
    for(i=0;i<4;i++)//遍历四个方向
    {
        for(j=1;j<=m;j++)//遍历各个距离1-k
        {
            x=X+dd[i][0]*j;//取点
            y=Y+dd[i][1]*j;
            if(x>=0&&y>=0&&x<n&&y<n)//判断越界
            {
                if(map[x][y]>map[X][Y])//下一个点必须比当前点的数值大
                {
                    k=dfs(x,y);//k记录下一个节点(x,y)的最大值
                    l=MM(l,k);//挑选最大
                }
            }
        }
    }
    sum[X][Y]=l+map[X][Y];//可以走各个点的最大值中最大的那个+当前点的数值=当前点的最大值
    return sum[X][Y];//返回当前点的最大值
}
int main (void)
{
    int i,j,k,l;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==-1&&m==-1)break;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                scanf("%d",&map[i][j]);
            }
        }
        memset(sum,0,sizeof(sum));
        l=dfs(0,0);
        printf("%d\n",l);
    }
    return 0;
}

感觉记忆化搜索是对搜索过程中的某些状态进行存储来去除重复搜索的耗时


HDU--1078--FatMouse and Cheese--记忆化搜索