P1434 [SHOI2002]滑雪题解

这道题个人是从记忆化搜索起手的,之前没怎么用过,也算是通过这道题区分了一下记忆化搜索(队列和递归)和动态规划之间比较小的区别,心得都写在注释里了

记忆化搜索和动态规划相比,记忆化搜索算是略微复杂的通解,因为动态规划是考虑到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);
}

第一篇题解,以后也会用这样的方式记录自己的心得和体悟,特别是不会的,觉得有意思的题目

好好加油

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值