这道题个人是从记忆化搜索起手的,之前没怎么用过,也算是通过这道题区分了一下记忆化搜索(队列和递归)和动态规划之间比较小的区别,心得都写在注释里了
记忆化搜索和动态规划相比,记忆化搜索算是略微复杂的通解,因为动态规划是考虑到for循环中的遍历顺序而创建的转移方程,
/// 但是如果for循环无法建立这样的转移方程(for循环只能从左到右或者从右到左,从上到下或者从下到上)
那么只能用较复杂的记忆化搜索,记忆化搜索是不一定能用队列的dfs(因为涉及到队列的时候一般是先高层再底层维护,递归则相反)
///因为记忆化搜索需要不断维护底层(如果底层能改变的话),并且把不会变动的内容记忆下来用递归,相反用队列
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e2+10;
int dp[maxn][maxn];
int pos[maxn][maxn];
int mx[5] = {0,1,-1,0,0};
int my[5] = {0,0,0,1,-1};
int r,c; //c是x轴,r是y轴
int dfs(int y,int x){
if(dp[y][x] != 0)
return dp[y][x];
dp[y][x] = 1; //不写这个起点的dp= 0;!!!!!!!!!!!!!!!!
int x1,y1;
for(int i = 1;i<=4;i++){
x1 = x+mx[i];
y1 = y+my[i];
if(x1>=1&&x1<=c&&y1>=1&&y1<=r&&pos[y1][x1]<pos[y][x]) //这里不能加上dp[y1][x1]!=0的条件,因为反正会返回的
{
dfs(y1, x1);
dp[y][x] = max(dp[y][x], dp[y1][x1] + 1);
}
}
return dp[y][x];
}
//这个dfs是如果原先这个点没有被触碰到,那么进行递归,找到几种可能到达这个点的点,再往复操作找到触碰过的,或者边界点,然后从底层递归返回进行维护数组
//main函数里,要求每一个点都要dfs是防止有不同的最佳起点,和碰不到的点
//这题的dfs只是单纯的去维护dp数组,因此我们在维护完成以后,返回dp[y][x];
int main(){
int ans = 0; //不初始化害死人
scanf("%d%d",&r,&c);
for(int i = 1;i<=r;i++)
for(int z = 1;z<=c;z++)
scanf("%d",&pos[i][z]);
for(int i = 1;i<=r;i++)
for(int z = 1;z<=c;z++)
ans = max(ans,dfs(i,z));
printf("%d",ans);
}
第一篇题解,以后也会用这样的方式记录自己的心得和体悟,特别是不会的,觉得有意思的题目
好好加油