本题应该是练习记忆化搜索非常不错的一道题
并没有什么花哨的解法233 一个中规中矩的记忆化搜索
不明白记忆化搜索的同学看这边:
记忆化搜索:因为普通搜索时,我们有时可能会用到之前所搜索到的结果,这时如果我们再次搜索就显得没有必要了(会浪费很多时间呢),所以如果我们已经记录了之前搜索的答案不就可以直接用之前的搜索答案了么
举个例子:
在求斐波那契数时,我们需要求第i个数,必须先知道i前面两个数,即:
f[i]=f[i-1]+f[i-2]
如果此时我们要求f[4]那么我们理应求出f[3]和f[2],而此时若要求你再求出f[6]时,就一定会用到f[5]和f[4],此时若我们未记录出f[4]的结果,那么我们就不得不再走一遍求f[4]时所走的路,显然,若之前计算出f[4]时我们就记录其结果就免去了走冤枉路咯(^∇^*)
核心代码:
if(map[nx][ny]<map[x][y]){
step[x][y]=max(step[x][y],1+dfs(nx,ny));//若可以继续向四周走那么我们就能更新现在所在点的步数咯(题目要求的是最大可走的步数)
} 完整代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 200;//数据并不大
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
int r,c,ans;
int map[maxn][maxn],step[maxn][maxn];
int dfs(int x,int y){
if(step[x][y]) return step[x][y];//一开始每个点的步数都应为0;如果当前这个点已知其最大步数说明之前该点已被计算过就不用再重复计算了(这不是废话么- -||);
step[x][y]=1;//既然这是一个从未走过的点那么现在来到该点至少都会使其步数为1
for(int i=0;i<4;i++){//四个可行的方向
int nx=x+dx[i],ny=y+dy[i];
if(map[nx][ny]<map[x][y]){
step[x][y]=max(step[x][y],1+dfs(nx,ny));//代码核心
}
}
return step[x][y];//返回值给上一个dfs调用
}
int main(){
ios::sync_with_stdio(false);
scanf("%d%d",&r,&c);
//初始化处理
for(int i=0;i<=c+1;i++){//将边界的高度设为无限高这样就免去了判断是否超出地图限制
map[i][0]=map[i][c+1]=1e9;
}
for(int i=0;i<=r+1;i++){
map[0][i]=map[r+1][i]=1e9;
}
//读入每个点的数据
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
scanf("%d",&map[i][j]);
}
}
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
ans=max(dfs(i,j),ans);//每一个点都跑一边dfs,答案取最大的就是题目要求了
}//因为有记忆化的缘故即使每个点都跑一边dfs也不会用很多时间 }//即是说:有的点的最大步数已经被记录,就不会再去重新跑dfs而是直接可以把现成的答案拿来用(记忆化搜索的精髓)
printf("%d",ans);
return 0;
}