[AcWing] 901. 滑雪(C++实现)记忆化搜索例题
1. 题目
2. 读题(需要重点注意的东西)
思路:
一句话思路:考虑从四个方向滑过来的最大值,那么当前值f(x,y)就等于四个方向滑过来的最大值+1。
将四个方向滑过来的最大值记为f(a,b),则f(x,y) = f(a,b)+1
,再一步步递归进去回溯出答案。
代码实现思路:
3. 解法
---------------------------------------------------解法---------------------------------------------------
#include<iostream>
#include<cstring>
using namespace std;
const int N = 310;
int n,m;
int g[N][N];
int f[N][N];
// -------------问题二:这两个数组是什么意思?-------------------
int dx[4] = {-1,0,1,0},dy[4] = {0,-1,0,1};
int dp(int x,int y){
// if(f[x][y] != -1) return f[x][y]; 记忆化搜索的核心!!
if(f[x][y] != -1) return f[x][y]; // 如果这个点已经计算过了,直接返回即可,这就是记忆化搜索
f[x][y] = 1;
for(int i = 0;i < 4;i++){
int a = x + dx[i],b = y + dy[i];
if(a >= 1 && a <= n && b >= 1 && b <= m&& g[a][b] > g[x][y]){
f[x][y] = max(f[x][y],dp(a,b)+1);
}
}
return f[x][y];
}
int main(){
cin >> n >> m;
for(int i = 1;i <= n;i++)
for(int j = 1 ; j <= m;j++)
cin >> g[i][j];
//---------------问题一:为什么要初始化为-1?-----------------
memset(f,-1,sizeof f);
int res = -1;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
res = max(res,dp(i,j));
}
}
cout << res << endl;
return 0;
}
可能存在的问题(所有问题的位置都在上述代码中标注了出来)
问题一:为什么要将 f 初始化为-1?
问题一回答:这里实际上就是记忆化搜索的核心!
先将其初始化为-1
memset(f,-1,sizeof f);
然后在递归dp时,判断
if(f[x][y] != -1) return f[x][y];
则如果这个点已经计算过了,直接返回即可,这就是记忆化搜索,减少了重复的计算。
问题二:这两个数组是什么意思?
问题二回答:用于遍历四个方向上的值
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; // 偏移量
for (int i = 0; i < 4; i ++ )
int a = x + dx[i], b = y + dy[i]; // for循环出四个方向
4. 可能有帮助的前置习题
- 遍历四个方向上节点的方法—[AcWing]844. 走迷宫(C++实现)bfs的思想
5. 所用到的数据结构与算法思想
- 动态规划
- 记忆化搜索
6. 总结
记忆化搜索的例题,理解思想并自行推导出代码。
遍历四个方向上的节点的方法:
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; // 偏移量
for (int i = 0; i < 4; i ++ )
int a = x + dx[i], b = y + dy[i]; // for循环出四个方向