记忆化搜索(hdu1078)

记忆化搜索实际上是递归来实现的,但是递归的过程中有许多的结果是被反复计算的,这样会大大降低算法的执行效率,因此我们可以将已经计算出来的结果开辟一个数组dp[][]保存起来,当之后的计算用到的时候直接取出结果,避免重复运算,从而提高效率。

比如HUD1078:
题意:给出n*n的格子,每个格子有食物,问一只老鼠每次走最多k步所能吃到的最多的食物,而且,每次吃的食物要比上一次多(加一个判断,后一个格子里的食物>前一个格子里的)

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int m[110][110],dp[110][110],to[4][2]= {0,1,1,0,-1,0,0,-1 };
int k,n;
int dfs(int x,int y)
{
	int tx,ty,i,j;
	if (dp[x][y])
		return dp[x][y];//如果搜索过了,dp就会有值, 
					//而且这个值是四周搜索过后的最大值。直接返回储存值就可以
       //没有搜索过的话开始搜索,从当前点向四周搜		 
	for (i=0; i<4; i++)
	{
		for (j=1; j<=k; j++)//每次走的步数
		{
			tx=x+to[i][0]*j;
			ty=y+to[i][1]*j;
			if (tx>=0&&tx<n&&ty>=0&&ty<n)//下个节点
			{
				if (m[tx][ty]>m[x][y])
				{
					dp[x][y]=max(dp[x][y],dfs(tx,ty)+m[tx][ty]);
					// 后个节点的食物大于前个节点,可以走,接下来看看能不能取到最优
				}
			}
		}
	}//没有搜索过,寻找四周落脚点的最大值储存,然后下一步。 
	return dp[x][y];
}
int main()
{
	while(~scanf("%d %d",&n,&k))
	{
		if (n==-1&&k==-1)
		break;
		int i,j;
		memset(m,0,sizeof(m));
		memset(dp,0,sizeof(dp));

		for (i=0; i<n; i++)
		{
			for (j=0; j<n; j++)
				scanf("%d",&m[i][j]);
		}
		printf("%d\n",dfs(0,0)+m[0][0]);
	}
	return 0;
}
posted @ 2020-09-25 19:30  索饮  阅读(118)  评论(0)    收藏  举报