递归——深度优先搜索(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
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为 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)——以滑雪问题为例(自顶而下)的更多相关文章
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)
需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- 【算法入门】深度优先搜索(DFS)
深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...
- 深度优先搜索 DFS 学习笔记
深度优先搜索 学习笔记 引入 深度优先搜索 DFS 是图论中最基础,最重要的算法之一.DFS 是一种盲目搜寻法,也就是在每个点 \(u\) 上,任选一条边 DFS,直到回溯到 \(u\) 时才选择别的 ...
- python 递归深度优先搜索与广度优先搜索算法模拟实现
一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件2.找出这一次和上一次关系3.假设当前 ...
- 深度优先搜索(DFS)
[算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一 ...
- HDU(搜索专题) 1000 N皇后问题(深度优先搜索DFS)解题报告
前几天一直在忙一些事情,所以一直没来得及开始这个搜索专题的训练,今天做了下这个专题的第一题,皇后问题在我没有开始接受Axie的算法低强度训练前,就早有耳闻了,但一直不知道是什么类型的题目,今天一看,原 ...
- 广度优先(bfs)和深度优先搜索(dfs)的应用实例
广度优先搜索应用举例:计算网络跳数 图结构在解决许多网络相关的问题时直到了重要的作用. 比如,用来确定在互联网中从一个结点到另一个结点(一个网络到其他网络的网关)的最佳路径.一种建模方法是采用无向图, ...
- matlab练习程序(广度优先搜索BFS、深度优先搜索DFS)
如此经典的算法竟一直没有单独的实现过,真是遗憾啊. 广度优先搜索在过去实现的二值图像连通区域标记和prim最小生成树算法时已经无意识的用到了,深度优先搜索倒是没用过. 这次单独的将两个算法实现出来,因 ...
随机推荐
- JS RegExp对象(正则表达式)
笔记整理自:廖雪峰老师的JS教程 正则表达式语法:https://www.runoob.com/regexp/regexp-tutorial.html 目录 创建方式 方式一 方式二 简单使用 判断正 ...
- Ajax不允许缓存方法
AJAX请求后台时会自动缓存,客户端发起请求首先请求缓存,第一次请求即由缓存再请求服务器,返回数据时同样先返回到缓存再展示再客户端.但是如果数据要求随时性呢,数据变化频率高呢?那么如何不让ajax设置 ...
- push自定义动画
// // ViewController.m // ViewControllerAnimation // // Created by mac on 15/5/26. // Copyright ...
- k8s之Pod基础概念
1. 资源限制 Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象.一个Pod代表着集群中运行的一个进程.kubernetes中其他大多数组件都是围绕着Pod来 ...
- Python中set集合常用操作
功能 Python符号 Python方法 备注 交集 & intersection, intersection_update &:取两者交集>>> set3 = se ...
- python解释器的安装以及解释器多版本共存
版本介绍 python创始人:gukido(龟叔) python1.X 原始版本,几乎不用 python2.x 最高版本2.7(2020年之后不再维护) python3.x 最高版本3.9(一般用3. ...
- 有个姑娘叫history
文章目录 常用参数 history的一些用法 修改history命令默认保存的数量 来给history穿衣服 让我们重新认识一下history history命令用于显示用户以前执行过的历史命令,并且 ...
- Vue2.0源码学习(1) - 数据和模板的渲染(上)
准备 一.首先去GitHub上把vue源码download下来,传送门:https://github.com/vuejs/vue 二.搭建一个vue-cli跑起来,用于代码调试,不看着代码动起来只看源 ...
- python中try...except的用法
num = [1,2,0,3,1.5,'6'] for x in num: try: # 尝试执行下列代码 print (6/x) except ZeroDivisionError: print('0 ...
- C#控制树莓派入门
何为树莓派 许久没有写博客了,十二月份西安疫情的影响,居家隔离了一个多月,在其期间,学习了一下树莓派,觉得硬件还是挺有意思的,刚好也看到了巨硬有提供使用c#用来开发树莓派应用的解决方案叫Net Iot ...
