记忆化搜索$||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. pythonl操作数据库

    目录 今日内容详细 Navicat软件 提示 练习题 pymysql模块 sql注入 navicat可视化界面操作数据库 数据库查询题目讲解(多表操作) python如何操作MySQL(pymysql ...

  2. 推荐一款Python开源库,技术人必备的造数据神器!

    1. 背景 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,要么需要手动制造一些数据.由于现在的业务系统数据多种多样,千变万化.在手动制造数据的 ...

  3. python 输出日志到文件和控制台

    import logging # 第一步,创建一个logger logger = logging.getLogger() logger.setLevel(logging.INFO) # Log等级总开 ...

  4. Scala 基础(十二):Scala 函数式编程(四)高级(二)参数(类型)推断、闭包(closure)、函数柯里化(curry)、控制抽象

    1  参数(类型)推断 参数推断省去类型信息(在某些情况下[需要有应用场景],参数类型是可以推断出来的,如list=(1,2,3) list.map() map中函数参数类型是可以推断的),同时也可以 ...

  5. less基础

    less less的含义: less是一种动态样式语言,属于css预处理器的范畴,它扩展了css语言,增加了变量.Mixin.函数等特性,使css更易维护和扩展. 此外,less既可以在客户端上运行, ...

  6. 响应式布局rem、rem方法封装、移动端响应式布局

    相信大家在做移动端的时候都会做各个手机的适配这种适配就是响应式布局在之前做网站的响应式从pc到手机用的是媒体查询 @media screen and (max-width: 300px){} 最大宽度 ...

  7. [ArcEngine二次开发]为Feature的属性赋值

    在创建FeatureClass之后,需要为FeatureClass添加Features,在为Feature的字段赋值时,代码大致如下: 在这里赋值的时候,出现了一个错误: The operation ...

  8. 为什么阿里、头条、美团这些互联网大厂都在用Spring Boot?

    前言 自 2014 年发布至今,Spring Boot 的搜索指数 一路飙升.没错 Spring Boot 越来越火了,作为一名行走一线的 Java 程序员,你可能在各个方面感受到了 Spring B ...

  9. 盘点JMeter不为人知那一些细节

    Jmeter工作原理 向服务器提交请求,并从服务器取回请求返回的结果.即建立一个线程池,多线程运行取样器产生大量负载,在运行过程中通过断言来验证结果的正确性,通过监听器来记录测试结果. 文章内容以Jm ...

  10. Database Identifiers - SID

    These options include your global database name and system identifier (SID). The SID is a unique ide ...