记忆化搜索实际上是递归来实现的,但是递归的过程中有许多的结果是被反复计算的,这样会大大降低算法的执行效率,因此我们可以将已经计算出来的结果开辟一个数组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
",dfs(0,0)+m[0][0]);
}
return 0;
}