AcWing 901. 滑雪 题解 记忆化搜索

本文介绍了记忆化搜索的概念,它实际上是一种动态规划的递归实现方式。通过一个向右滑动的例子,解释了状态计算的原理,即在能够向右滑动的情况下,当前位置的高度大于右侧位置及其可滑到的区域,因此在计算当前位置的最大路径时,考虑右侧的最大路径加1。代码展示了如何使用C++实现这一算法,遍历四个方向并找到最大路径。最终,通过遍历整个矩阵并计算每个点为起点的最大路径,找出最长路径。该算法用于解决寻找最大连续区域的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

在这里插入图片描述
在这里插入图片描述


思路:记忆化搜索

记忆化搜索的本质还是DP,但是实现方式和传统DP不一样,采用的是一种递归的实现方式。
在这里插入图片描述
图片有误,转换中向上的公式和向下的公式颠倒了
解释状态计算为什么可以这么算?
以向右滑举例:
如果在(i,j)(i,j)(i,j)处可以向右滑,那么f[i,j]=f[i,j+1]+1f[i,j]=f[i,j+1]+1f[i,j]=f[i,j+1]+1
如果可以向右滑,那么(i,j)(i,j)(i,j)处的高度一定大于(i,j+1)(i,j+1)(i,j+1)处以及它能滑到的路径上所有区域的高度
所以要求f[i,j]f[i,j]f[i,j],实际是求f[i,j+1]f[i,j+1]f[i,j+1],再+1+1+1
但是有四个方向可能可以滑,所以取这四个方向可能额可以滑的最大值。


代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=310;
int h[N][N],f[N][N];
int r,c;
int dx[4]={1,-1,0,0},dy[4]={0,0,-1,1};  //上下左右移动位移方向数组
int dp(int x,int y)
{
    int &v=f[x][y];   //用引用v来代替f[x][y]
    if(v!=-1) return v; //如果v!=-1,证明v的值已经计算出来了,不用再算了,这一步很关键,省去了多余的计算,不然会TLE
    v=1;  //在滑向第一个区域前,每个点自身算一个区域
    for(int i=0;i<4;i++)   //遍历四个方向
    {
        int a=x+dx[i],b=y+dy[i];
        if(a>=1&&a<=r&&b>=1&&b<=c&&h[x][y]>h[a][b])   //如果滑的方向的区域还在雪场内
            v=max(v,dp(a,b)+1);   //算最大值
    }
    return v;
}
int main()
{
    scanf("%d%d",&r,&c);
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
            scanf("%d",&h[i][j]);
    memset(f,-1,sizeof(f));  //把dp数组初始化为0
    int res=0;  //记录结果
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
            res=max(res,dp(i,j));   //算出以每个点为起点的最大路径长度,作比较算出其中最大的
    printf("%d",res);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alkali!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值