深度优先搜索(详情参考noi.cgyounger.com深度优先搜索专项)

扫地机器人

Mike同学在为扫地机器人设计一个在矩形区域中行走的算法,Mike是这样设计的:先把机器人放在出发点(1,1)点上,机器人在每个点上都会沿用如下的规则来判断下一个该去的点是哪里。规则:优先向右,如果向右不能走(比如:右侧出了矩形或者右侧扫过了)则尝试向下,向下不能走则尝试向左,向左不能走则尝试向上;直到所有的点都扫过。
Mike为了验证自己设计的算法是否正确,打算先模拟一下这个算法,每当机器人走过一个单元格时,会在单元格内标记一个数字,这个数字从1开始,每经过一个单元格数字会递增1,直到所有的单元格都扫一遍,也就是所有的单元格都标记过数字,机器人会自动停止。
比如:如果机器人按照上面的规则,清扫一个3×4大小的矩形区域,那么标记数字的结果如下图所示。
image.png
再比如:如果机器人按照上面的规则,清扫一个5×5大小的矩形区域,那么标记数字的结果如下图所示。
image.png
请你帮助Mike设计一个程序,按照上面的规则,将一个n×m大小的矩形,标记一下数字,输出最终标记的结果。
输入
一行内有2个两个整数n和m,用空格隔开,分别代表矩形区域的行数(高)和列数(宽)。
1<n,m<10。
输出
输出按题意机器人走过每个点之后,标记数字的结果,每个数字输出时场宽设置为3。
输入样例 1

3 4

输出样例 1

 1  2  3  4  
10 11 12  5
 9  8  7  6
#include <bits/stdc++.h>
using namespace std;
int s = 0, n, m;
int maze[10][10];//maze机器人行走的路线
int fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//依题意右下左上四方向设计
void dfs(int x, int y, int s) {
	if (s > n * m) {//判断机器人是否走完所有单元格
		return ;
	} else {
		maze[x][y] = s;//给当前位置进行标记
		for (int i = 0; i < 4; i++) {//按右下左上顺序移动
			int nx = x + fx[i][0], ny = y + fx[i][1];//移动后得到新的坐标位置
			if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && maze[nx][ny] == 0) {
                //判断该位置上是否可以达到
				dfs(nx, ny, s + 1);
			}
		}

	}
}

int main() {
	cin >> n >> m;//输入单元格宽高区域
	dfs(1, 1, 1);//机器人从(1,1)--左上角位置出发,起始值为1,进入深搜
	//深搜结束后输出单元格赋值情况
    for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cout << setw(3) << maze[i][j];//要求宽设置为3
		}
		cout << endl;
	}
	return 0;
}

迷宫出口

描述
一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n×n的格点组成,每个格点只有2种状态,0和1,前者表示可以通行后者表示不能通行。
同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。
如果起点或者终点有一个不能通行(为1),则看成无法办到。
输入
第11行是一个正整数n(1≤n≤100),表示迷宫的规模是n×n的。
接下来是一个n×n的矩阵,矩阵中的元素为0或者1。
再接下来一行是4个整数halaℎhblb,描述A处在第ha行 第la列,B处在第hb行 第lb列。
输出
能办到则输出YES,否则输出NO。
输入样例 1

3
0 1 1 
0 0 1 
1 0 0 
1 1 3 3

输出样例 1

YES
#include <bits/stdc++.h>
using namespace std;
int ans=0, m, n, ha, la, hb, lb;
int maze[11][11];//maze记录数组信息

int fx[4][2]={{1, 0}, {0, 1}, {-1, 0}, {0, -1}};//右下左上四方向


void dfs(int x, int y) {
	if (x == hb && y == lb) {//走到终点则跳出深搜
		ans++;
		return ;
	} else if (maze[x - 1][y] == 1 && maze[x + 1][y] == 1 && maze[x][y - 1] == 1 && maze[x][y + 1] == 1) {//四面皆不可走则跳出深搜
		return ;
	} else {
		maze[x][y] = 1;
		for (int i = 0; i < 4; i++) {//按右下左上顺序移动
			int nx = x + fx[i][0], ny = y + fx[i][1];//移动后得到新的坐标位置
			if (nx >= 1 && nx <= n && ny >= 1 && ny <= n && maze[nx][ny] == 0 ) {//在数组范围内且未走过
				maze[nx][ny] = 1;
				dfs(nx, ny);
				maze[nx][ny] = 0;
			}//回溯法
		}
		maze[x][y] = 0;
	}
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> maze[i][j];//输入迷宫信息
		}

	}
	cin>>ha>>la>>hb>>lb;//输入起始和结束位置
	dfs(ha, la);//从ha,la位置进入深搜
	if (ans!=0) {//若ans为零则没有路径
		cout << "YES";
	} else {
		cout << "NO";
	}
	return 0;
}

数池塘(四方向)

描述
农夫约翰的农场可以表示成N×M个方格组成的矩形。由于近日的降雨,在约翰农场上的不同地方形成了池塘。每一个方格或者有积水(W)或者没有积水(.)。
农夫约翰打算数出他的农场上共形成了多少池塘。一个池塘是一系列相连的有积水的方格,每一个方格周围的四个方格都被认为是与这个方格相连的。现给出约翰农场的图样,要求输出农场上的池塘数。
输入
第11行:由空格隔开的两个整数:N和M;
第2…N+1行:每行M个字符代表约翰农场的一排方格的状态。每个字符或者是W或者是.,字符之间没有空格。
数据范围
1≤N,M≤100。
输出
输出只有1行,输出约翰农场上的池塘数。

输入样例 1
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
输出样例 1
13
#include <bits/stdc++.h>
using namespace std;
char maze[110][110];
int n, m, ans = 0;

int fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//右下左上四方向

void dfs(int x, int y) {
	maze[x][y] = '.';
	for (int i = 0; i < 4; i++) {//按右下左上顺序移动
		int nx = x + fx[i][0], ny = y + fx[i][1];//移动后得到新的坐标位置
		if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && maze[nx][ny] == 'W') {//在数组范围内且有积水
			dfs(nx, ny);
		}
	}
}

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {//输入农场信息
			cin >> maze[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (maze[i][j] == 'W') {//寻找水洼
				++ans;//找到一个ans+1
				dfs(i, j);//用深搜的方式在该池塘位置填土
			}
		}
	}
	cout << ans;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值