一、问题:滑雪

问题描述:小明喜欢滑雪,为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。小明想知道在一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

1  2  3  4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

 

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为 24-17-16-1 . 当然 25-24-23-...-3-2-1 更长。事实上,这是最长的一条.

  • 输入描述:输入的第一行表示区域的行数 R和列数 C (1 ≤R,C≤100). 下面是 RR 行,每行有 C 个整数,代表高度 h ,0≤h≤10000.

  • 输出描述:输出最长区域的长度.

  • 样例输入

 

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

  

  • 样例输出:25

二、问题分析

  • 简述:从二维数组中,找到一条满足条件(一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小)节点的个数。

  • 可以采用DFS算法,搜索出以一个节点为起点,最远可以抵达的地方,并记录长度(其中节点个数)

三、问题的图解

1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

  

依此输入为例(以21所在位置为起点)

下面展示三张搜索的过程

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105,mod=1e9+7;
int a[N][N];
int n,m;
int tmp; int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int h[N][N];//记录坐标(i,j)的答案,以(i,j)为起点的路径最长多少 int dfs(int x,int y){//以(x,y)为起点的遍历
int mx=0;
if(h[x][y])return h[x][y];// 记录为0的路径避免重复计算
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[nx][ny]<a[x][y]){//递归出口:找不到更低的去处
mx=max(mx,dfs(nx,ny));//递归体:只要能在周围找到能去的路径,递归调用去找能去路径的最大值
}
}
return h[x][y]=mx+1;//最终求出周围路径最大值+1就是(x,y)为起点的最长滑坡长度
}
// dfs: 这个算法会尽可能深的搜索树的分支 ,#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105,mod=1e9+7;
int a[N][N];
int n,m;
int tmp; int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int h[N][N];//记录坐标(i,j)的答案,以(i,j)为起点的路径最长多少 int dfs(int x,int y){//以(x,y)为起点的遍历
int mx=0;
if(h[x][y])return h[x][y];// 记录为0的路径避免重复计算
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[nx][ny]<a[x][y]){//递归出口:找不到更低的去处
mx=max(mx,dfs(nx,ny));//递归体:只要能在周围找到能去的路径,递归调用去找能去路径的最大值
}
}
return h[x][y]=mx+1;//最终求出周围路径最大值+1就是(x,y)为起点的最长滑坡长度
}
// dfs: 这个算法会尽可能深的搜索树的分支 ,时间复杂度为O(N)
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++){
dfs(i,j);
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ans=max(ans,h[i][j]);
}
}
printf("%d\n",ans);
}
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++){
dfs(i,j);
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ans=max(ans,h[i][j]);
}
}
printf("%d\n",ans);
}

  

五、递归思想总结

  • 归纳假设:一个节点为起点的最深路径为周围节点最深路径加一

  • 递归模型

    • f(x,y):路径的长度

    • f(x,y)==1 当四周找不到更低的地方(无处可去)(递归出口)

    • f(x,y)==max(f(x-1,y),f(x+1,y),f(x,y+1),f(x,y-1))+1(递归体)

六、感悟:

先将大问题分解成一个基础问题+一个小一层级问题,并用递归模型表示出来,利用图文结合方法加快效率。最后落地。

递归——深度优先搜索(DFS)——以滑雪问题为例(自顶而下)的更多相关文章

  1. 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)

    深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...

  2. 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)

    需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...

  3. 深度优先搜索DFS和广度优先搜索BFS简单解析

    转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...

  4. 【算法入门】深度优先搜索(DFS)

    深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...

  5. 深度优先搜索 DFS 学习笔记

    深度优先搜索 学习笔记 引入 深度优先搜索 DFS 是图论中最基础,最重要的算法之一.DFS 是一种盲目搜寻法,也就是在每个点 \(u\) 上,任选一条边 DFS,直到回溯到 \(u\) 时才选择别的 ...

  6. python 递归深度优先搜索与广度优先搜索算法模拟实现

    一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件2.找出这一次和上一次关系3.假设当前 ...

  7. 深度优先搜索(DFS)

    [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一 ...

  8. HDU(搜索专题) 1000 N皇后问题(深度优先搜索DFS)解题报告

    前几天一直在忙一些事情,所以一直没来得及开始这个搜索专题的训练,今天做了下这个专题的第一题,皇后问题在我没有开始接受Axie的算法低强度训练前,就早有耳闻了,但一直不知道是什么类型的题目,今天一看,原 ...

  9. 广度优先(bfs)和深度优先搜索(dfs)的应用实例

    广度优先搜索应用举例:计算网络跳数 图结构在解决许多网络相关的问题时直到了重要的作用. 比如,用来确定在互联网中从一个结点到另一个结点(一个网络到其他网络的网关)的最佳路径.一种建模方法是采用无向图, ...

  10. matlab练习程序(广度优先搜索BFS、深度优先搜索DFS)

    如此经典的算法竟一直没有单独的实现过,真是遗憾啊. 广度优先搜索在过去实现的二值图像连通区域标记和prim最小生成树算法时已经无意识的用到了,深度优先搜索倒是没用过. 这次单独的将两个算法实现出来,因 ...

随机推荐

  1. TensorFlow 卷积神经网络实用指南 | iBooker·ApacheCN

    原文:Hands-On Convolutional Neural Networks with TensorFlow 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 不要担心自己的形象,只关心 ...

  2. Java程序设计(2021春)——第五章输入输出笔记与思考

    Java程序设计(2021春)--第五章输入输出笔记与思考 本章概览: 异常处理简介 程序运行时,环境.操作等可能出现各种错误.故障,我们希望程序具有容错能力,给出错误信息.面向对象的程序设计里有异常 ...

  3. Nginx实现跨域配置详解

    主要给大家介绍了关于Nginx跨域使用字体文件的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 问题描述 今天在使用子域名访问根域名的CSS时,发现字体无法显示,在确保CSS和Font字 ...

  4. ARC基本概念

    1.什么是ARC Automatic Reference Counting,自动引用计数,即ARC,可以说是WWDC2011和iOS5所引入 的最大的变革和最激动人心的变化.ARC是新的LLVM 3. ...

  5. ElasticSearch 基本介绍和读写搜索过程

    cluster 代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的.es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部 ...

  6. Spring IOC-基于XML配置的容器

    Spring IOC-基于XML配置的容器 我们先分析一下AbstractXmlApplicationContext这个容器的加载过程. AbstractXmlApplicationContext的老 ...

  7. Solution -「多校联训」种蘑菇

    \(\mathcal{Description}\)   Link.   给定一棵含有 \(n\) 个结点的树,设 \(S\) 为其中的非空联通子集,求 \[\sum_{S}(\gcd_{u\in S} ...

  8. [LeetCode]7. 整数反转(Java)

    原题地址: reverse-integer 题目描述: 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果. 如果反转后整数超过 32 位的有符号整数的范围 [−2^31,  ...

  9. suse 12 二进制部署 Kubernetets 1.19.7 - 第08章 - 部署kube-scheduler组件

    文章目录 1.8.部署kube-scheduler 1.8.0.创建kube-scheduler请求证书 1.8.1.生成kube-scheduler证书和私钥 1.8.2.创建kube-schedu ...

  10. JMM之Java中锁概念的分类总结

    在Java的并发编程中不可避免的涉及到锁.从不同维护可以将锁进行不同的分类,如下: 1.乐观锁和悲观锁(根据读写操作的比例划分) 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数 ...