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

来源:互联网 发布:python json库 编辑:程序博客网 时间:2024/05/22 07:07

思路:

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 <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <stack>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define REP(i,k,n) for(int i=k;i<n;i++)#define REPP(i,k,n) for(int i=k;i<=n;i++)#define scan(d) scanf("%d",&d)#define scann(n,m) scanf("%d%d",&n,&m)#define LL long long#define maxn 105#define mod 100000007/*inline int read(){    int s=0;    char ch=getchar();    for(; ch<'0'||ch>'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<n && ny>=0 && ny<n && vis[nx][ny]==0 && mp[nx][ny]>mp[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<n;i++)            for(int j=0;j<n;j++)            scanf("%d",&mp[i][j]);       printf("%d\n",dfs(0,0));    }    return 0;}

0 0
原创粉丝点击