<蓝桥杯备考刷题>P1434 [SHOI2002] 滑雪(经典的记忆化搜索题目

      原题链接:P1434 [SHOI2002] 滑雪

我们先上题目:

在讲题目之前我先来讲一讲记忆化搜索

何为记忆化搜索? 实际上就是DP+DFS (一般来说都可以一比一还原成递推类型)

虽然对于DP问题,本蒟蒻就是永远都想不到变量的含义QAQ,能暴力则暴力不能暴力则跳过

他可以将整体搜索的时间复杂度从指数直接降低到乘法

我们先来做一遍基本的dfs暴力:

思路还是比较简单,就是枚举每一个点

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int arr[N][N];
int n,m;
int ans;
int dx[4]{1,0,0,-1};
int dy[4]{0,1,-1,0};

int dfs(int x,int y){
    int res = 1;
    for(int i = 0;i<4;i++){
        int ax = x+dx[i];
        int ay = y+dy[i];
        if(ax>=1&&ax<=n&&ay>=1&&ay<=m&&arr[ax][ay]<arr[x][y]){
            res = max(res,dfs(ax,ay)+1);
        }
    }
    return res;
}
int main(){
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            cin>>arr[i][j];
        }
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            ans = max(ans,dfs(i,j));
        }
    }
    cout<<ans;
}

ok 如果我猜得没错的话。。。

嗯超时了

因为数据量在100所以整体复杂度为4的100次方(每一个点都要判断上下左右)就一定超时

但是实际上,我们在这里面的dfs中走了很多重复的路

我们每次都走重复的路 当然就会很浪费时间,此时就出现了记忆化搜索!

当我们搜索到之前走过的路,我们直接选择返回,减少接下来的继续搜索

直接上代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int arr[N][N];
//记忆化,我通常都用dp取名字,因为和dp类似
//一维为x坐标,二维y坐标
int dp[N][N];
int n,m;
int ans;
int dx[4]{1,0,0,-1};
int dy[4]{0,1,-1,0};

int dfs(int x,int y){
    if(dp[x][y]) return dp[x][y];
    int res = 1;
    for(int i = 0;i<4;i++){
        int ax = x+dx[i];
        int ay = y+dy[i];
        if(ax>=1&&ax<=n&&ay>=1&&ay<=m&&arr[ax][ay]>arr[x][y]){
            res = max(res,dfs(ax,ay)+1);
        }
    }
    return dp[x][y] = res;
}
int main(){
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            cin>>arr[i][j];
        }
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            ans = max(ans,dfs(i,j));
        }
    }
    cout<<ans;
}

这样就可以完美过了

注:

不同的记忆化题目 对于dp数组的定义不同(维度意义也不同)所以为什么dp难了QAQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值