HDU FatMouse and Cheese (记忆化搜索+dp思想)

思路:

1)最朴素的思想就是,枚举从(0,0)出发所有可能路径,求出每一条路径的ans,打擂台比较,最大的即为答案;
2)从(0,0)出发的子问题是从(x,y)(x>0,y>0)出发,显然,对于每一个子问题都有着确定独立的最优解;所以解决了所有子问题就解决了此题;

3)dp[x][y] 记录从(x,y)出发能吃到的奶酪,所以dp[x][y]是+=路径上所有的dp[nx][ny]的奶酪

4)问题是,对于一个100*100的图每次重复枚举所有可能是很夸张的;所以可以用到一个其实很常用的东西:记忆化搜索;

(x,y) 为当前位置,(nx,ny)是下一步,在回溯的时候,肯定又会,产生(nx,ny),这时候在dfs的一开始给他加上一个标记:如果dp[nx][ny]已经有答案了,就不必再求;

if(dp[x][y])  return dp[x][y];
否则,比如求dp[0][0]的时候,必然要将其路径上的值再算一遍,重复计算的次数达到可怕的地步;

这个标记就也称之为记忆化操作,实际上造成的效果避免了重复操作,只留下必要操作,就相当于把dfs变成了普通几层循环dp。

/* ***********************************************
Author        :angon
************************************************ */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define REP(i,k,n) for(int i=k;i'9'; ch=getchar());
    for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';
    return s;
}
inline void print(int x)
{
    if(!x)return;
    print(x/10);
    putchar(x%10+'0');
}
*/
int n,k,dp[maxn][maxn],mp[maxn][maxn],vis[maxn][maxn];
int dir[][2]={0,1,0,-1,1,0,-1,0};
int dfs(int x,int y)
{
    if(dp[x][y])
        return dp[x][y];
    int temp=0,ans=0;
    for(int i=1;i<=k;i++)
    {
        for(int j=0;j<4;j++)
        {
            int nx=x+dir[j][0]*i;
            int ny=y+dir[j][1]*i;
            if(nx>=0 && nx=0 && nymp[x][y])
            {
                vis[nx][ny]=1;  //加这一句能稍快一点,不加亦可
                temp = dfs(nx,ny);
                vis[nx][ny]=0;
                ans = max(ans,temp);
            }
        }
    }
    dp[x][y] = ans + mp[x][y];  //回溯的时候计算dp[x][y],自底向上,自终点向起点
    return dp[x][y];
}


int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(scanf("%d%d",&n,&k))
    {
        if(n==k && n==-1) break;
        memset(dp,0,sizeof(dp));
        memset(mp,0,sizeof(mp));
        memset(vis,0,sizeof(vis));
        for(int i=0;i

你可能感兴趣的:(HDU FatMouse and Cheese (记忆化搜索+dp思想))