dfs + 记忆化搜索

上篇文章给大家带来了dfs的走迷宫,那么今天的文章继续拓展dfs的相关知识。

咱们在做题的时候往往会遇到类似数塔这种题,给个n层数塔:

                 7

           3          8

      3         4          6  

7         4          7           8

              .......... 

请你从第一层开始以一种走法走到最后一层使路过的数加和最大?

在分析这道题的时候,我们可以用动态规划的方法来解决,设置二维dp[i][j]数组含义为第i层第j列的总和最小经历值,所以其状态方程为dp[i][j] = max(dp[i + 1][j],dp[i + 1][j + 1]) + dp[i][j]

所以遍历顺序+初始化:

for(int j = 0;j <= n;j++)
{
	dp[n][j] = a[n][j];//将最后一层赋值初始化
}
for(int i = n - 1;i >= 1;i--)//由n - 1层到第一层递推
{
	for(int j = 1;j <= i;j++)
	{
		dp[i][j] = max(dp[i + 1][j],dp[i + 1][j + 1]) + a[i][j];
	}
}

其实根据动态规划的分析思路,我们不难发现这题跟咱们的dfs走迷宫也是有些相似的。在分析这道题之前,咱们先用dfs的思路来分析这道题,首先判断递归的方向,咱们在走迷宫是通过枚举横纵坐标来判断走的方向,这道题咱们可以定义一个二维塔数组存储数,通过dfs(i,j)分别代表维数组两个参数来控制方向.....

int dfs(int i,int j)
{
	if(i == n)  return a[i][j];//递归到最后一层返回
	return dp[i][j] = max(dfs(i + 1,j),dfs(i + 1,j + 1)) + a[i][j];
}

But,这种暴力搜索我们会搜索所有的可能情况,会有很多中间值被重复计算,所以咱们这里会用到记忆化搜索,通过存储每一位置的最小值来达到避免重复运算,代码如下....

int dfs(int i,int j)
{
	if(i == n)  return a[i][j];
	if(dp[i][j] > 0)  return dp[i][j];//记忆
	return dp[i][j] = max(dfs(i + 1,j),dfs(i + 1,j + 1)) + a[i][j];
}

这样就会将复杂度优化到O(n次方)次计算。记忆化搜索的目的是跳过已经算过的重复值来减小递归的次数

好了,今天的分享到这里了,别忘记三连支持,感谢收看!!!

你可能感兴趣的:(深度优先,算法)