【DFS】深度优先搜索 最长路径问题详解

DFS深搜

看看题 P1683 入门

入门

题目描述

不是任何人都可以进入桃花岛的,黄药师最讨厌像郭靖一样呆头呆脑的人。所以,他在桃花岛的唯一入口处修了一条小路,这条小路全部用正方形瓷砖铺设而成。有的瓷砖可以踩,我们认为是安全的,而有的瓷砖一踩上去就会有喷出要命的毒气,那你就死翘翘了,我们认为是不安全的。你只能从一块安全的瓷砖上走到与他相邻的四块瓷砖中的任何一个上,但它也必须是安全的才行。

由于你是黄蓉的朋友,她事先告诉你哪些砖是安全的、哪些砖是不安全的,并且她会指引你飞到第一块砖上(第一块砖可能在任意安全位置),现在她告诉你进入桃花岛的秘密就是:如果你能走过最多的瓷砖并且没有死,那么桃花岛的大门就会自动打开了,你就可以从当前位置直接飞进大门了。

注意:瓷砖可以重复走过,但不能重复计数。

输入格式

第一行两个正整数 W W W H H H,分别表示小路的宽度和长度。

以下 H H H 行为一个 H × W H\times W H×W 的字符矩阵。每一个字符代表一块瓷砖。其中,. 代表安全的砖,# 代表不安全的砖,@ 代表第一块砖。

输出格式

输出一行,只包括一个数,即你从第一块砖开始所能安全走过的最多的砖块个数(包括第一块砖)。

样例 #1

样例输入 #1

11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........

样例输出 #1

59

提示

数据规模与约定

对于全部的测试点,保证 1 ≤ W , H ≤ 20 1 \leq W,H\le 20 1W,H20

  • 看一看代码,含注释解析👇
#include<bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false),cout.tie(0),cin.tie(0);//加快输入输出
using namespace std;
const int N = 1e6;
int n,m,A,B,sum = 0;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};//四个值代表搜索的四个方向
bool vis[21][21];//标记数组
char arr2[21][21];

void dfs(int x,int y)//从(x,y)开始搜索
{
	for(int i = 0;i <= 3;i++)//重复4次(4种运动情况)
	{
		int xx = x + dx[i],yy = y + dy[i];//下一个搜索的坐标,用(x,y)更新(xx,yy)
		if(xx >= 1 && xx <=m && yy >= 1 && yy <= n && arr2[xx][yy] == '.' && vis[xx][yy] == 0)//保证是在地图之内,不越界,并保证走为未被标记的安全地点
		{
			vis[xx][yy] = 1;//标记
			dfs(xx,yy);//递归,继续搜索
		}
	}
}


int main()
{
	IOS;//加快输入输出
	cin>>n>>m;//读入长宽
	for(int i = 1;i <= m;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			cin>>arr2[i][j];
			if(arr2[i][j] == '@')
			{
				A = i;
				B = j;//标记起点,用变量存储坐标值
			}
		}
	}
	vis[A][B] = 1;//将起点标记
	dfs(A,B);//从起点开始搜索
	for(int i = 1;i <= m;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			if(vis[i][j] == 1)	sum++;//将走过的路数一遍
		}
	}
	cout<<sum;//输出最长路径
}

DFS的根本还是一种“递归”算法,一条路走到黑,结束之后再执行原dfs的下一条程序。
就像一条树,从起点开始,不停向下延申分支。

像本题就是用抽象的树形结构,在二维地图内,走出了最长的路,也就找到了所有安全砖

对于初次学习dfs和bfs的同学一定不要急,将代码自己多写几遍,没事就看看,慢慢就理解了😊

  • 30
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值