您的位置:首页 > 其它

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

2016-04-08 00:49 375 查看
思路:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: