算法篇之记忆化搜索
记忆化搜索
概念:
- 记忆化搜索就是深度优先搜索的一种优化策略,
记忆化搜索=深度优先搜索形式+动态规划思想
- 由于dfs本质是暴力搜索,没有很好地处理重叠子问题,因此很低效
- 记忆化算法在求解地时候还是按照自顶向下的顺序,但是每求解一个状态,就将它的解保存下来
- 求解最优解问题
优点:
- 解决了深度优先搜索中的重叠子问题要多次遍历的问题
- 搜索还可以剪枝,可能剪去大量不必要的状态
缺点:
- 对于同样的问题,如果用动态规划解决而是用了记忆化搜索会使得效率有所降低
dfs函数组成:
- 得有搜索边界即结束条件,以及处理
- 对当前状态的检查,如果结果已经记录,则直接返回返回
- 从当前状态到下一个状态的转移,当前状态最优解的记录
- 对结果的返回
- 核心点:状态转移方程的确定。dp[state]=optimal(dp[state],dfs(next state)+cost);
代码模板:
//type为类型,state为状态,在图论中一般都是横竖坐标
type dfs(state){
if(结束条件){
处理;
return type; //返回对应类型的值
}
if(当前状态的解已被记录) return dp[state];
//跟动态规划一样或者说跟dfs一样遍历下一个状态
for each next state{
if(检查当前状态是否符合约束条件){
dp[state]=optimal(dp[state],dfs(next state)+cost);
}
}
return dp[state];
}
例题代码实现:
-
蓝桥杯题:
滑行
#include <iostream> using namespace std; int mp[105][105], n, m,dp[105][105]; int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1}; int dfs(int x,int y){ if(dp[x][y]!=-1) return dp[x][y]; dp[x][y]=1; for(int i=0;i<4;++i){ int px=x+dx[i]; int py=y+dy[i]; if(px>=0&&py>=0&&px<n&&py<m&&mp[px][py]<mp[x][y]){ dp[x][y]=max(dp[x][y],dfs(px,py)+1); } } return dp[x][y]; } int main(){ for(int i=0;i<n;++i){ for(int j=0;j<m;++j){ cin>>mp[i][j]; dp[i][j]=-1; } } int cnt=1; for(int i=0;i<n;++i){ for(int j=0;j<m;++j){ cnt=max(cnt,dfs(i,j)); } } cout<<cnt<<endl; return 0; }