这题记一下记忆化搜索:
记忆化搜索实际上是递归来实现的(刚好符合dfs),但是递归的过程中有许多的结果是被反复计算的,这样会大大降低算法的执行效率。
而记忆化搜索是在递归的过程中,将已经计算出来的结果保存起来,当之后的计算用到的时候直接取出结果,避免重复运算,因此极大的提高了算法的效率。
对于这题, 在DFS回溯的过程中,更新从当前格子出发能够得到的最大价值,以避免重复的计算。
因为回溯时,上一个格子的所有可能情况都已经考虑过了,也就是说上一个格子的状态已经是最优的了,所以直接用上一个格子的值来更新当前格子。在当前格子的所有方向都回溯完时,当前格子也就达到了最优值,继续更新之后的。
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <stack>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=110;
int dp[maxn][maxn],map[maxn][maxn],n,k;
int nxt[4][2]= {0,1,1,0,-1,0,0,-1};
int dfs(int x,int y)
{
int i,j,tx,ty,sum=0;
if(!dp[x][y])//记忆化搜索的操作,成立,就说明在DFS过程中这个坐标曾经被搜索过,那就可以直接返回数值
{
for (i=1; i<=k; i++)
for (j=0; j<4; j++)
{
tx=x+nxt[j][0]*i;
ty=y+nxt[j][1]*i;
if (tx>=0&&tx<n&&ty>=0&&ty<n&&map[tx][ty]>map[x][y])
{
sum=max(sum,dfs(tx,ty));//更新最优解,因为最优解需要dfs从下一层带上来
}
}
//用最优解更新当前格子,表示从当前格子出发能够获得的最多的奶酪
dp[x][y]=sum+map[x][y];//把从[x,y]处出发的最优答案记录下来,下次再遇到[x,y]就可以直接返回答案
}
return dp[x][y];
}
int main()
{
int i,j;
while(~scanf("%d%d",&n,&k)&&n!=-1&&k!=-1)
{
memset(dp,0,sizeof(dp));
for (i=0; i<n; i++)
for (j=0; j<n; j++)
scanf("%d",&map[i][j]);
printf("%d
",dfs(0,0));
}
return 0;
}