算法总结—深度优先搜索DFS
深度优先搜索(DFS)
往往利用递归函数实现(隐式地使用栈)。
深度优先从最开始的状态出发,遍历所有可以到达的状态。由此可以对所有的状态进行操作,或列举出所有的状态。
1.poj2386 Lake Couting
题意:八连通被认为连接在一起,求总共有多少个水洼?
Sample Input:
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
Sample Output
3 思路:从任意W开始,一次DFS把连通的.全部变为W,遍历图直到没有.为止,进行DFS次数即为水洼的个数。
代码:
#include<iostream>
using namespace std;
int N, M;
char pond[][]; //global variable
void dfs(int i, int j){ // 注意参数设计,要不要返回值
pond[i][j] = '.';
for(int dx = -; dx <= ; ++dx){ //八连通遍历方式,四连通往往事先开好数组,见后续题目
for(int dy = -; dy <= ; ++dy){
int x = i + dx, y = j + dy;
if(x >= && x < N && y >= && y < M && pond[x][y] == 'W'){
dfs(x,y);
}
}
}
return;
}
int main(){
cin >> N >> M;
for(int i = ; i < N; ++i){
for(int j = ; j < M; ++j){
cin >> pond[i][j];
}
} int count = ;
for(int i = ; i < N; ++i){
for(int j = ; j < M; ++j){
if(pond[i][j] == 'W'){
dfs(i,j);
count ++;
}
}
}
cout << count << endl;
}
2.poj1979 Red and Black
题意:@表示起点,可以上下左右四方向走,"."为黑色,可以走,“#”为红色,不可以走,问可以到达多少个黑色位置?
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13
思路:从起点处DFS遍历即可,当前点为“.”则将其改为“#”,result++,并以该点出发继续遍历。
代码:
#include<iostream>
using namespace std;
char rect[][];
int result = ; //全局的result
int dx[] = {-,,,}; //四连通处理方法
int dy[] = {,,-,};
int W = , H = ;
void dfs(int sx, int sy){
rect[sx][sy] = '#';
result++;
for(int i = ; i < ; ++i){
int x = sx + dx[i], y = sy + dy[i];
if(x >= && x < H && y >= && y < W && rect[x][y] == '.'){
dfs(x,y);
}
}
return ;
}
int main(){
while(W != && H != ){
cin >> W >> H;
if(W == && H == ){
return ;
}
int sx, sy;
for(int i = ; i < H; ++i){
for(int j = ; j < W; ++j){
cin >> rect[i][j];
if(rect[i][j] == '@'){
sx = i;
sy = j;
}
}
}
dfs(sx, sy);
cout << result << endl;
result = ;
}
return ;
}
3.aoj0118 Property Distribution
题意: 苹果是@,梨是#, 蜜柑是*。 四连通且相同品种在一个区域。计算每组数据区域的个数。
Sample Input:
10 10
####*****@
@#@@@@#*#*
@##***@@@*
#****#*@**
##@*#@@*##
*@@@@*@@@#
***#@*@##*
*@@@*@@##@
*@*#*@##**
@****#@@#@
0 0
Output for the Sample Input
33
思路:类似第一题的池塘数个数的思路,DFS遍历,将遍历完毕的节点改为不同于上述三种标志的第四种标志,如“X”,
并且在DFS函数中加入标志参数用于判断同类水果区域,一次DFS,result++,当所有标志为X时,遍历结束。
代码:
#include<iostream>
using namespace std;
char garden[][];
int H = , W = ;
int result = ;
int dx[] = {-,,,};
int dy[] = {,,-,};
void dfs(int sx, int sy,char c){ //加入char判断是否同一类
garden[sx][sy] = 'x';
for(int i = ; i < ;++i){
int x = sx + dx[i], y = sy + dy[i];
if(x >= && x < H && y >= && y < W && garden[x][y] == c){
dfs(x,y,c);
}
}
return;
}
int main(){
while(H != && W != ){
cin >> H >> W;
if(H == && W == ){
return ;
}
for(int i = ; i < H; ++i){
for(int j = ; j < W; ++j){
cin >> garden[i][j];
}
}
for(int i = ; i < H; ++i){
for(int j = ; j < W; ++j){
if(garden[i][j] != 'x'){
dfs(i,j,garden[i][j]);
result++;
}
}
}
cout << result << endl;
result = ;
}
}
4.aoj0033 Ball
题意:A管进球,B,C管出球,给定如球顺序,判断能否移动挡板,使得B,C出球顺序均为从下往上标号递增。![]()
Sample Input
2
3 1 4 2 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
Output for the Sample Input
YES
NO
思路:DFS遍历,一个参数记录当前到第几个球,另外两个记录当前B,C顶端球得数值,以便于比较。
代码:
#include<iostream>
using namespace std;
int A[];
bool dfs(int start, int topB, int topC){ //有返回值的DFS
if(start == ){ //最后一个球啦
if(A[start] > topB || A[start] > topC){
return true;
}
else{
return false;
}
}
bool b1 = false, b2 = false;
if(A[start] > topB){ //B可以放,放进去试
b1 = dfs(start+, A[start], topC);
}
if(A[start] > topC){ //C可以放,放进去试
b2 = dfs(start+,topB,A[start]);
}
return (b1 || b2 ); //B,C都不可以放的时候,返回false,否则true
}
int main(){
int N;
cin >> N;
for(int i = ; i < N; ++i){
for(int j = ; j < ; ++j){
cin >> A[j];
}
bool result = dfs(,,);
if(result == true){
cout << "YES" << endl;
}
else{
cout << "NO" <<endl;
}
}
return ;
}
5. poj3009 Curling 2.0
题意:
可以沿上下左右走到障碍物,碰到障碍物后停下,障碍物消失,然后可以继续出发,出界算失败,超过十步算失败,问能否从S到G,
不能输出-1,能输出最少步数。(0路径,1障碍物,2起点,3终点)
Sample Input
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0
Sample Output
1
4
-1
4
10
-1
思路:这种走到底的题目也可以用DFS,设计成无返回值,到达3后比较当前值与已有最小值的大小。注意走到底的写法(while)
代码:
#include<iostream>
#include<cstring>
#include<limits.h>
using namespace std;
int board[][];
int W = , H = ;
int dx[] = {-,,,};
int dy[] = {,,-,};
int sx, sy,minStep = INT_MAX;
void dfs(int sx,int sy,int step){ //设计成无返回值,当board[i][j] == 3时比较当前 step+1 与最小的step并更新
if(step >= ){ //剪枝
return;
}
for(int i = ; i < ;++i){
int x = sx + dx[i], y = sy + dy[i];
if(x >= && x < H && y >= && y < W && board[x][y] != ){
while(x >= && x < H && y >= && y < W && board[x][y] != ){ //走到底的判断
if(board[x][y] == ){
if(step + < minStep){
minStep = step + ;
break;
}
}
x += dx[i];
y += dy[i];
if(board[x][y] == ){
board[x][y] = ;
dfs(x - dx[i], y - dy[i], step + );
board[x][y] = ; // 恢复状态
}
}
}
}
return;
} int main(){
while(W != && H != ){
cin >> W >> H;
if(W == && H == ){
return ;
}
memset(board,,sizeof(board));
for(int i = ; i < H; ++i){
for(int j = ; j < W; ++j){
cin >> board[i][j];
if(board[i][j] == ){
sx = i;
sy = j;
}
}
}
dfs(sx,sy,);
if(minStep == INT_MAX){
cout << "-1" << endl;
}
else{
cout << minStep << endl;
}
minStep = INT_MAX;
}
return ;
}
6.poj1321 棋盘问题
题意:n*n矩阵形状的棋盘(“#”为可摆放棋盘区域,“.”为不可摆放空白区域),要摆放k个棋子,同行同列不能有两个,共多少种方案?
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
Sample Output
2
1 思路:DFS的思路,一行一行的确定摆放位置,开一个数组place[8]记录哪一列已经有摆放。
注意k如果小于N时,可以有某一行不摆放元素,所以代码24行 DFS(row+1,num) 必须添加。 代码:
#include<iostream>
#include<cstring>
using namespace std;
int N = ,K = ;
char chess[][];
int result = ;
int placed[] = {}; //记录该列是否有摆放
void dfs(int row,int num){
if(num == K){ //摆放成功,方案数++
result++;
return;
}
if(row == N){
return;
} for(int i = ; i < N; ++i){
if(chess[row][i] == '#' && placed[i] == ){
placed[i] = ;
dfs(row + , num + );
placed[i] = ;
}
}
dfs(row+,num); //!容易忽略 }
int main(){
while(N != - && K != -){
cin >> N >> K;
if(N == - && K == -){
return ;
}
memset(chess,,sizeof(chess));
memset(placed,,sizeof(placed));
for(int i = ; i < N;++i){
for(int j = ; j < N; ++j){
cin >> chess[i][j];
}
}
dfs(,);
cout << result << endl;
result = ;
} }
算法总结—深度优先搜索DFS的更多相关文章
- 【算法入门】深度优先搜索(DFS)
深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...
- [算法&数据结构]深度优先搜索(Depth First Search)
深度优先 搜索(DFS, Depth First Search) 从一个顶点v出发,首先将v标记为已遍历的顶点,然后选择一个邻接于v的尚未遍历的顶点u,如果u不存在,本次搜素终止.如果u存在,那么从u ...
- 深度优先搜索 DFS 学习笔记
深度优先搜索 学习笔记 引入 深度优先搜索 DFS 是图论中最基础,最重要的算法之一.DFS 是一种盲目搜寻法,也就是在每个点 \(u\) 上,任选一条边 DFS,直到回溯到 \(u\) 时才选择别的 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)
需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- 算法与数据结构基础 - 深度优先搜索(DFS)
DFS基础 深度优先搜索(Depth First Search)是一种搜索思路,相比广度优先搜索(BFS),DFS对每一个分枝路径深入到不能再深入为止,其应用于树/图的遍历.嵌套关系处理.回溯等,可以 ...
- 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法
深度优先(DFS) 深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接 ...
- [算法入门]——深度优先搜索(DFS)
深度优先搜索(DFS) 深度优先搜索叫DFS(Depth First Search).OK,那么什么是深度优先搜索呢?_? 样例: 举个例子,你在一个方格网络中,可以简单理解为我们的地图,要从A点到B ...
随机推荐
- [转]模拟HttpContext 实现ASP.NET MVC 的单元测试
众所周知 ASP.NET MVC 的一个显著优势即可以很方便的实现单元测试,但在我们测试过程中经常要用到HttpContext,而默认情况下单元测试框架是不提供HttpContext的模拟的,本文通过 ...
- USB开发库文件分析
stm32f10x_it.c: 该文件中包含 USB 中断服务程序,由于 USB 中断有很多情况,这里的中断服务程序只是调用 usb_Istr.c 文件中的 USB_Istr 函数,由 USB_Ist ...
- linux下find查找命令用法
Linux下find命令在目录结构中搜索文件,并执行指定的操作.Linux下find命令提供了相当多的查找条件,功能很强大.由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时 ...
- class-dump-z下载地址
支持MAC.Linux.Win和iOS各个版本 http://download.csdn.net/detail/yukang1989/8414567
- POJ1948Triangular Pastures(DP)
POJ1948http://poj.org/problem?id=1948 题目大意就是说给你n个木棍让你用它们摆成一个三角形 使得这个三角形的面积最大. 这个题我之前想的时候一直纠结怎么通过之前的 ...
- redis的文件事件处理器
前言 C10K problem提出了一个问题,如果1w个客户端连接到server上,间歇性的发送消息,有哪些好的方案? 其中的一种方案是,每个线程处理多个客户端,使用异步I/O和就绪通 ...
- (剑指Offer)面试题31:连续子数组的最大和
题目: 输入一个整型数组,数组里有正数也有负数,数组中一个或连续多个整数组成一个子数组,求所有子数组的和的最大值.要求时间复杂度为O(n) 思路: 1.数组累加 从头到尾逐个累加数组中的每个数字,当累 ...
- 获取select当前选择的值和文本
<html> <head> <script type="text/javascript"> function EE(obj) { alert(& ...
- Oracle主键自增的实现
create sequence seq_字段名_表名 minvalue 1 maxvalue 999999999999999999999999999 start with 1 increment by ...
- DISCUZ X2更换域名注意事项
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...