题解 [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 ...
随机推荐
- 树的深度———树形DP
题目描述 输入 输出 样例 样例输入 样例输出 7 分析 这道题数据有1000000,把每一个顶点都枚举一次显然不现实,肯定会T掉 所以,我们还是从图中找规律 按照习惯,我们先把1号节点作为根节点模拟 ...
- centos彻底删除文件夹创建文件
centos彻底删除文件夹.文件命令(centos 新建.删除.移动.复制等命令: 1.新建文件夹 mkdir 文件名 新建一个名为test的文件夹在home下 view source1 mkdir ...
- Django---进阶12
目录 Auth模块 方法总结 如何扩展auth_user表 项目开发流程 表设计 作业 Auth模块 """ 其实我们在创建好一个django项目之后直接执行数据库迁移命 ...
- 重学 Java 设计模式:实战模版模式「模拟爬虫各类电商商品,生成营销推广海报场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 黎明前的坚守,的住吗? 有人举过这样一个例子,先给你张北大的录 ...
- vue+element-ui JYAdmin后台管理系统模板-集成方案【项目搭建篇2】
项目搭建时间:2020-06-29 本章节:讲述基于vue/cli, 项目的基础搭建. 本主题讲述了: 1.跨域配置 2.axios请求封装 3.eslint配置 4.环境dev,test,pro(开 ...
- 【XCTF】ics-05
信息: 题目来源:XCTF 4th-CyberEarth 标签:PHP.伪协议 题目描述:其他破坏者会利用工控云管理系统设备维护中心的后门入侵系统 解题过程 题目给了一个工控管理系统,并提示存在后门, ...
- 攻防世界FlatScience
访问robots.txt发现 admin.php和login.php 在admin.php和login.php分别尝试注入 发现login.php页面存在注入,并且根据报错得知数据库类型为sqlite ...
- The solution for apt-get update Err 404
最近在ubuntu 12.10上执行sudo apt-get update 命令后出现了如下错误: Ign http://extras.ubuntu.com natty/main Translatio ...
- 微信小程序接口封装、原生接口封装、request、promise封装
相信大家在做微信小程序的时候会有很多地方需要调用接口,就和pc以及手机端一样,多个页面多次调用会有很多状态,那为了节省大家的开发时间就会需要给请求的接口做一些简单封装,便于开发,在这里我用了两个js, ...
- QSignalMapper的使用和使用场景
目录 QSignalMapper的使用和使用场景 常见场景 下面是参考.可看可不看 这篇写的不错,搬运为Markdown了 可以看一下 参考 QSignalMapper的使用和使用场景 QSignal ...