原题链接:P1434 [SHOI2002] 滑雪
我们先上题目:
在讲题目之前我先来讲一讲记忆化搜索
何为记忆化搜索? 实际上就是DP+DFS (一般来说都可以一比一还原成递推类型)
虽然对于DP问题,本蒟蒻就是永远都想不到变量的含义QAQ,能暴力则暴力不能暴力则跳过
他可以将整体搜索的时间复杂度从指数直接降低到乘法
我们先来做一遍基本的dfs暴力:
思路还是比较简单,就是枚举每一个点
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int arr[N][N];
int n,m;
int ans;
int dx[4]{1,0,0,-1};
int dy[4]{0,1,-1,0};
int dfs(int x,int y){
int res = 1;
for(int i = 0;i<4;i++){
int ax = x+dx[i];
int ay = y+dy[i];
if(ax>=1&&ax<=n&&ay>=1&&ay<=m&&arr[ax][ay]<arr[x][y]){
res = max(res,dfs(ax,ay)+1);
}
}
return res;
}
int main(){
cin>>n>>m;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
cin>>arr[i][j];
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
ans = max(ans,dfs(i,j));
}
}
cout<<ans;
}
ok 如果我猜得没错的话。。。
嗯超时了
因为数据量在100所以整体复杂度为4的100次方(每一个点都要判断上下左右)就一定超时
但是实际上,我们在这里面的dfs中走了很多重复的路
我们每次都走重复的路 当然就会很浪费时间,此时就出现了记忆化搜索!
当我们搜索到之前走过的路,我们直接选择返回,减少接下来的继续搜索
直接上代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int arr[N][N];
//记忆化,我通常都用dp取名字,因为和dp类似
//一维为x坐标,二维y坐标
int dp[N][N];
int n,m;
int ans;
int dx[4]{1,0,0,-1};
int dy[4]{0,1,-1,0};
int dfs(int x,int y){
if(dp[x][y]) return dp[x][y];
int res = 1;
for(int i = 0;i<4;i++){
int ax = x+dx[i];
int ay = y+dy[i];
if(ax>=1&&ax<=n&&ay>=1&&ay<=m&&arr[ax][ay]>arr[x][y]){
res = max(res,dfs(ax,ay)+1);
}
}
return dp[x][y] = res;
}
int main(){
cin>>n>>m;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
cin>>arr[i][j];
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
ans = max(ans,dfs(i,j));
}
}
cout<<ans;
}
这样就可以完美过了
注:
不同的记忆化题目 对于dp数组的定义不同(维度意义也不同)所以为什么dp难了QAQ