[洛谷P1434] [SHOI2007]滑雪

题目链接:

here we go

题外话:

谁能想到这是一道咕了两年的\(AC\)呢……当年是在搜索还半懂不懂的时候遇到的这道题,感觉真是难得要命()所以一直拖着不做,后面就下意识地逃避了搜索相关的内容(慢慢变菜
(然后学树形\(dp\)数位\(dp\)的时候强行线性\(dp\)经常推不出被搞疯了)
咳咳,所以终于回来把这道题做了,也算是还债了吧。
有时候感觉自己真是像一头从小被拴在木桩上的象,习惯了之后就从来没想过去挑战一下尝试一下什么的,越来越惰怠,当然只能越来越弱了啊(

题目分析:

首先这个题是一个很经典的记忆化搜索例题,经典到讲记忆化搜索十个教练有八个都会把这道题搬出来当例题。
所谓记忆化搜索,其本质仍然是递归。但由于递归时有许多重复的状态,所以会耗时巨大,而记忆化搜索以动态规划的方式记录了之前所计算过的状态,下次需要这个状态的时候不需要重新递归计算,而是可以直接拿来用,这样可以节省大量时间。

对于这个题,我们记录搜索到每一个点的最大路径长度,这样下次需要用这个点的时候就不需要再一次递归到头,而是直接调用即可。

顺便,我看题解里有不少判边界的(无限加高的,打判断的),其实可以反过来考虑,把滑雪看成爬坡,每一个\(dfs\)的点只能往高处走,这样递归的判断应该是

    if(Map[x][y]<Map[go_x][go_y]) {
        ...
    }

而\(Map[]\)数组的初始值是\(0\),即边界的\(Map\)值都是\(0\),所以走到边界的时候这个判断语句的返回值永远是\(false\),直接规避了边界问题

对着每一个点\(dfs\)一遍(即把每个点当做终点搜一遍)取最大即可。

代码:

#include <bits/stdc++.h>
#define N (100+5)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c;
    c = getchar();
    while (!isdigit(c)) {
        if(c == '-') f = -f;
        c = getchar();
    }
    while (isdigit(c)) {
        cnt = cnt * 10 + c - '0';
        c = getchar();
    }
    return cnt * f;
}
int r, c;
int ans=-1;
int mapp[N][N], step[N][N];
const int fx[4] = {0, 1, 0, -1};
const int fy[4] = {1, 0, -1, 0};
int Dfs(int x, int y) {
    if(step[x][y]) return step[x][y];
    step[x][y] = 1;
    for (register int i = 0; i <= 3; i++) {
            int gx = x + fx[i]; int gy = y + fy[i];
            if(mapp[x][y] < mapp[gx][gy]) 
            step[x][y] = max(step[x][y], Dfs(gx, gy) + 1);
    }
    return step[x][y];
}
int main() {
    r = read();
    c = read();
    for (register int i = 1; i <= r; i++) 
        for (register int j = 1; j <= c; j++)
            mapp[i][j] = read();
            
    memset(step, 0, sizeof(step));
    for (register int i = 1; i <= r; i++) 
        for (register int j = 1; j <= c; j++)
            ans = max(ans, Dfs(i, j));
            
    printf("%d\n", ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值