C++记忆化搜索
前言(一些小废话)
C++中的记忆化搜索(Memoization)是一种优化技术,用于减少重复计算的开销。它常用于动态规划和递归问题中。
记忆化搜索和动态规划从根本上来讲就是一个东西,任何一个DP方程都能转为记忆化搜索 ,反之亦然。
我写这篇文章,是因为自己的DP基础薄弱,不易推出状态转移方程。实际上,DP的代码量更少,也更方便(在能推出状态转移方程的基础上)。
记忆化搜索的优缺点
优点
- 记忆化搜索可以避免搜到无用状态, 特别是在有状态压缩时
- 不需要注意转移顺序(这里的"转移顺序"指正常DP中for循环的嵌套顺序以及循环变量是递增还是递减)
- 边界情况非常好处理, 且能有效防止数组访问越界
- 对我这种蒟蒻来说写起来简单易懂
- 有些DP(如区间DP)用记忆化搜索写很简单但正常DP很难
缺点
- 不能滚动数组(虽然我也不大会),要滚动数组的话还是老老实实写DP吧
- 有些优化比较难加
- 由于递归, 有时效率较低但不至于 TLE (状压dp除外)
- 代码有点长
如何写记忆化搜索
不考虑DP
由暴搜开始思考
- 写出这道题的暴搜程序
- 将这个DFS改成"无需外部变量"的DFS
- 添加记忆化数组
例题:[NOIP2005 普及组] 采药
假设我P也不会,只会暴搜,你会得到:
#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,t;
int T[N],W[N];
int ans;
void dfs( int x , int time , int tans ) {
if(time < 0)
return;
if(x == n+1) {
ans = max(ans,tans);
return;
}
dfs(x+1,time,tans);
dfs(x+1,time-T[x],tans+W[x]);
}
int main() {
cin >> t >> n;
for(int i = 1; i <= n; i++)
cin >> T[i] >> W[i];
dfs(1,t,0);
cout << ans << endl;
return 0;
}
以及冰冷的30分
开始第二步,将这个DFS改成"无需外部变量"的DFS
引入问题:如何记录答案?
答:可以将DFS引入返回值
于是我们得到了:
#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,t;
int T[N],W[N];
int ans;
int dfs( int x , int time) {
if(x == n+1) {
return 0;
}
int dfs1 ,dfs2 = -1;
dfs1 = dfs(x+1,time);
if(time >= T[x]){
dfs2 = dfs(x+1,time-T[x]) + W[x];
}
return max(dfs1,dfs2);
}
int main() {
cin >> t >> n;
for(int i = 1; i <= n; i++)
cin >> T[i] >> W[i];
cout<<dfs(1,t)<<endl;
return 0;
}
别急着提交,因为我们只是去掉了"外部变量",却没有优化复杂度
接下来,我们添加记忆化数组
多测试几组样例发现,其实对于相同的x和time,DFS的返回值总是相同的(废话)
接下来引入记忆化数组"mem",用它来记录下DFS每一个返回值,每次DFS判断一下mem是否有值,若有值,直接返回mem;若无值,继续搜索(类似于剪枝)
于是我们得到了:
#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,t;
int T[N],W[N];
int mem[N][10*N];
int ans;
int dfs( int x , int time) {
if(mem[x][time] != 0){
return mem[x][time];
}
if(x == n+1) {
return 0;
}
int dfs1 ,dfs2 = -1;
dfs1 = dfs(x+1,time);
if(time >= T[x]){
dfs2 = dfs(x+1,time-T[x]) + W[x];
}
mem[x][time] = max(dfs1,dfs2);
return mem[x][time];
}
int main() {
cin >> t >> n;
for(int i = 1; i <= n; i++)
cin >> T[i] >> W[i];
cout<<dfs(1,t)<<endl;
return 0;
}
注意:mem数组千万不要开小了(作者亲自踩坑)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· 深度对比:PostgreSQL 和 SQL Server 在统计信息维护中的关键差异