记忆化搜索$||dp||$剪枝

先讲方法,代码待会上

方法一:记忆化搜索

这个方法不怎么解释,就是每搜索完一个高度的最长路径记录一下,以后搜索其他的点时如果走到了这条路就直接用记录的值计算就是了

方法二:$dp$

假设一个点的高度为H,周围四个点的高度分别为$\mathcal{H1,H2,H3,H4,}$$f[i][j]$代表从$(i,j)$滑的最长长度。如果$\mathcal{H}$大于周围四个点的一个,那么就可以滑到那一个点,也就是$f$[高的那个点]$=f$[矮的那个点]$\mathcal{+1}$,到这里就不难写出状态转移方程了:$f[i][j]=f[i+b_g][j+c_g]+\mathcal{1}$(前提:$a[i+b_g][j+c_g]<a[i][j]$),其中$a$数组为读入的高度,$b$、$c$数组为方向数组,$f$数组为这个点的最长路径长度。注意在计算长度之前要先将高度排序,然后再来算

方法3:剪枝

假如说当前的最大高度为$maxn$,搜索函数里的参数$num$(代表当前已经走过的长度),当前这个点的高度为$height$。如果$num+height<=maxn$,那么可以直接$return$(注意:这里我还没有枚举周围四个点)。假设你从这个点可以一路无阻碍的走到$\mathcal{1}$(也就是最优的情况),那么从这个点走的长度为$height$。但是如果已经走的长度加上从这个点的最优长度都小于等于最大长度的话,那么搜下去肯定是毫无意义的,果断剪枝。

除了这个以外,还可以加一个小小的剪枝(与其说是剪枝,不如说是特判):如果$maxn==n*m$,那么就可以直接输出答案了。因为整个地图的大小为$n*m$,若$maxn==n*m$的话就说明可以跑完整个地图,那么最大值无论如何也不会更新了,所以说这里就可以直接输出了(说不定可以过某些测试点呢)

接着附上代码:(由于本人比较懒,$dp$的代码搬$(chao)$运$(xi)$的一本通)

方法一:$(\mathcal{42}ms/\mathcal{928}KB)$(不知道为什么我的记忆化是$\mathcal{42}ms$,大佬都是$\mathcal{0}ms$,可能我太蒟了吧)

#include<cstdio>
#include<iostream>
using namespace std;
const int N=105;
int n,m,a[N][N],f[N][N]= {0},maxn,ans,b[4]= {1,0,-1,0},c[4]= {0,1,0,-1};
bool p[N][N];
inline void dfs(int x,int y,int num) {
int flag=0;
for(int i=0; i<4; i++) {
int xx=x+c[i],yy=y+b[i];
if(a[xx][yy]>=a[x][y]) continue;
if(f[xx][yy]) {
ans=max(ans,f[xx][yy]+num);
continue;
}
if(xx&&xx<=n&&yy&&yy<=m&&!p[xx][yy]) {
p[xx][yy]=1;
dfs(xx,yy,num+1);
p[xx][yy]=0;
}
}
if(!flag) {
ans=max(ans,num);
return;
}
}
int main() {
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) scanf("%d",&a[i][j]);
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
ans=0;
p[i][j]=1;
dfs(i,j,1);
p[i][j]=0;
f[i][j]=ans;
if(maxn<ans) maxn=ans;
}
}
printf("%d\n",maxn);
return 0;
}

方法二:$(\mathcal{33}ms/\mathcal{792}KB)$

#include<iostream>
#include<cstdio>
using namespace std;
int dx[5]= {0,-1,0,1,0},dy[5]= {0,0,1,0,-1};
long long r,c,i,j,p,t,ans;
long long m[101][101],f[101][101];
int search(int,int);
int main() {
cin>>r>>c;
ans=0;
for(i=1; i<=r; i++) {
for(j=1; j<=c; j++) cin>>m[i][j];
}
for(i=1; i<=r; i++) {
for(j=1; j<=c; j++) {
t=search(i,j);
f[i][j]=t;
if(t>ans) ans=t;
}
}
cout<<ans<<endl;
}
int search(int x,int y) {
int i,t,tmp,nx,ny;
if(f[x][y]>0) return f[x][y];
t=1;
for(i=1; i<=4; i++) {
nx=x+dx[i];
ny=y+dy[i];
if((nx>=1)&&(nx<=r)&&(ny>=1)&&(ny<=c)&&(m[x][y]<m[nx][ny])) {
tmp=search(nx,ny)+1;
if(tmp>t) t=tmp;
}
}
f[x][y]=t;
return t;
}

方法三:$(\mathcal{988}ms/\mathcal{1040}KB)$

#include<cstdio>
using namespace std;
const int N=105;
int n,m,a[N][N],maxn,b[4]= {1,0,-1,0},c[4]= {0,1,0,-1};
bool p[N][N]= {0};
inline void dfs(int x,int y,int num) {
int flag=0;
if(a[x][y]+num<maxn) return;
for(int i=0; i<4; i++) {
int xx=x+c[i],yy=y+b[i];
if(xx>0&&xx<=n&&yy>0&&yy<=m) {
if(a[xx][yy]>=a[x][y]) continue;//跳不过去
if(!p[xx][yy]) {
flag=1;
p[xx][yy]=1;
dfs(xx,yy,num+1);
p[xx][yy]=0;
}
}
}
if(!flag) {
if(maxn<num) maxn=num;
return;
}
}
int main() {
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) scanf("%d",&a[i][j]);
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(maxn==n*m) {
printf("%d\n",maxn);
return 0;
}
p[i][j]=1;
dfs(i,j,1);
p[i][j]=0;
}
}
printf("%d",maxn);
return 0;
}

题解 [SHOI2002]滑雪的更多相关文章

  1. [BFS]P1434 [SHOI2002]滑雪

    P1434 [SHOI2002]滑雪 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者 ...

  2. 洛谷[SHOI2002]滑雪题解

    什么破题啊 简直就是浪费我时间! 我每天还被我xf定目标了不知道嘛! 题目 朴素的搜索只能得90分 #include <cstdio> #include <iostream> ...

  3. 【dp】P1434 [SHOI2002]滑雪

    题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...

  4. 【题解】滑雪 luogu1434 记忆化搜索

    记忆化搜索入门题 题目 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在 ...

  5. P1434 [SHOI2002]滑雪

    题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...

  6. P1434 [SHOI2002]滑雪 dfs

    题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...

  7. 洛谷 P1434 [SHOI2002]滑雪

    这道题适合记忆化练手 毕竟总有些大佬虐题. 这个题有几个剪枝 1.记忆化 这个不用多说了吧 剪枝就是 如果 当前点到下面一个点的目前下降的高度+1 小于 下面那个点 能下降的高度 那么反过来,这个点不 ...

  8. 洛谷P1434 [SHOI2002]滑雪

    题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...

  9. 洛谷-P1434 [SHOI2002]滑雪 (记忆化搜索)

    题意:有一个\(R*C\)的矩阵,可以从矩阵中的任意一个数开始,每次都可以向上下左右选一个比当前位置小的数走,求走到\(1\)的最长路径长度. 题解:这题很明显看到就知道是dfs,但是直接爆搜会TLE ...

随机推荐

  1. REST,RPC和GraphQL应用场景,WebHooks、WebSocket、HTTP Streaming应用场景。

    一.请求--响应API. 请求--响应类的API的典型做法是,通过基于HTTP的Web服务器暴露一个/套接口.API定义一些端点,客户端发送数据的请求到这些端点,Web服务器处理这些请求,然后返回响应 ...

  2. [JAVA]《JAVA开发手册》规约详解

    [强制] 使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出 UnsupportedOperationExceptio ...

  3. 从 (a==1&&a==2&&a==3) 成立中看javascript的隐式类型转换

    下面代码中 a 在什么情况下会打印 1? var a = ?; if(a == 1 && a == 2 && a == 3){ console.log(1); } 这个 ...

  4. 萌新计划 PartⅠ

    Part Ⅰ web1-7 题目总体代码框架如下,其中过滤内容不同,大体上通过构造出id=1000类似的语句进行绕过,得到flag <?php # 包含数据库连接文件 include(" ...

  5. 神经网络结构:DenseNet

    论文地址:密集连接的卷积神经网络 博客地址(转载请引用):https://www.cnblogs.com/LXP-Never/p/13289045.html 前言 在计算机视觉还是音频领域,卷积神经网 ...

  6. SonarQube+Jenkins+Cppcheck实现C++代码扫描

    背景:公司部分项目是由C++进行开发,因此对此有需求. sonarqube:docker化安装(alpine系统),版本8.3.1 (build 34397) jenkins:docker化安装,版本 ...

  7. 初识:LevelDB

    初识:LevelDB 上篇文章缘起:BigTable可以说是已经把论文Bigtable: A Distributed Storage System for Structured Data中的内容掰扯的 ...

  8. 谈谈IT圈的门槛与学历的关系以及如何避免青春饭?

    一.关于我自己 我是一名80后的IT老兵,从今年出现疫情后,就感觉多少有些力不从心了,因为公司的业务做的不好,公司是做普惠金融的,疫情出现后,催收逾期就非常厉害,导致公司不敢大量放贷,从而就出现了公司 ...

  9. PyQt5事件处理

    事件介绍 事件的处理机制非常的复杂,属于PyQt底层的事,不必我们关心,学会使用就行.如果说事件是用来创建窗口,那么信号与槽就是用来对这个控件进行处理.事件属于低级的处理方式,信号与槽是高级的处理方式 ...

  10. 题解 洛谷 P4336 【[SHOI2016]黑暗前的幻想乡】

    生成树计数的问题用矩阵树定理解决. 考虑如何解决去重的问题,也就是如何保证每个公司都修建一条道路. 用容斥来解决,为方便起见,我处理时先将\(n\)减了1. 设\(f(n)\)为用\(n\)个公司,且 ...