题解 [SHOI2002]滑雪
记忆化搜索$||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]滑雪的更多相关文章
- [BFS]P1434 [SHOI2002]滑雪
P1434 [SHOI2002]滑雪 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者 ...
- 洛谷[SHOI2002]滑雪题解
什么破题啊 简直就是浪费我时间! 我每天还被我xf定目标了不知道嘛! 题目 朴素的搜索只能得90分 #include <cstdio> #include <iostream> ...
- 【dp】P1434 [SHOI2002]滑雪
题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...
- 【题解】滑雪 luogu1434 记忆化搜索
记忆化搜索入门题 题目 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在 ...
- P1434 [SHOI2002]滑雪
题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...
- P1434 [SHOI2002]滑雪 dfs
题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...
- 洛谷 P1434 [SHOI2002]滑雪
这道题适合记忆化练手 毕竟总有些大佬虐题. 这个题有几个剪枝 1.记忆化 这个不用多说了吧 剪枝就是 如果 当前点到下面一个点的目前下降的高度+1 小于 下面那个点 能下降的高度 那么反过来,这个点不 ...
- 洛谷P1434 [SHOI2002]滑雪
题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最长 ...
- 洛谷-P1434 [SHOI2002]滑雪 (记忆化搜索)
题意:有一个\(R*C\)的矩阵,可以从矩阵中的任意一个数开始,每次都可以向上下左右选一个比当前位置小的数走,求走到\(1\)的最长路径长度. 题解:这题很明显看到就知道是dfs,但是直接爆搜会TLE ...
随机推荐
- P4408 逃学的小孩 题解
题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听说要考试,Chris的父母就心 ...
- [Noip2016]蚯蚓 (单调队列)
题干 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓.蛐蛐国 ...
- 从零开始使用 Webpack 搭建 Vue3 开发环境
从零开始使用 Webpack 搭建 Vue3 开发环境 创建项目 首先需要创建一个空目录,在该目录打开命令行,执行 npm init 命令创建一个项目,这个过程会提示输入一些内容,完成后会自动生成一个 ...
- JavaScript动画实例:曲线的绘制
在“JavaScript图形实例:曲线方程”一文中,我们给出了15个曲线方程绘制图形的实例.这些曲线都是根据其曲线方程,在[0,2π]区间取一系列角度值,根据给定角度值计算对应的各点坐标,然后在计算出 ...
- Ant-Design-Vue中关于Form组件的使用
1.创建form表单的两种方式,不同的方式在js中创建表单的方式也不同 方式1:一般使用在搜索表单中,只需要双向绑定数据即可,那就使用这种方法即可 <template> <a-for ...
- oracle创建Javasource实现数据库备份
因客户需求,需要在业务系统中,菜单中的网页中的按钮中加入一个按钮,用于点击备份数据库 (环境:只配置了数据源连接oralce ,应用服务器和数据服务器不在一台机器,且数据库机器oracle操作系统账号 ...
- Python 如何生成 200 个激活码
请用 Python 如何生成 200 个激活码. 激活码的格式为asqE-9xRK-lqWU-QkMT 要求1: 使用随机生成时,生成数字概率为1/5,大写字母和小写字母概率各为2/5 要求2: 这2 ...
- 什么是viewstate,能否禁用?是否所用控件都可以禁用
viewstate用于在两次postback之间保持状态的一种机制禁用viewstate将不能在回发之间保存状态 当控件状态无关使用viewstate将造成性能问题时需要禁用viewstate Vie ...
- 小特跨境电商ERP桌面版 1.不止包括进销存 还能算毛利
经过近几年跨境电商ERP的开发,加上对跨境电商行业的业务积累,开发出一套适合中小跨境电商公司使用的ERP软件.欢迎选购.支持目前流行的各大电商平台,如速卖通.敦煌网.亚马逊.Shopee.Wish等. ...
- ThinkPHP5.0、5.1和6.0教程文档合集(免费下载)
我们都知道ThinkPHP是一个免费开源的,快速.简单的面向对象的轻量级PHP开发框架. ThinkPHP6主要更新了什么呢? 1. 支持PHP最新的强类型 2. PSR开发规范得了更广泛的应用 3. ...