深搜(DFS)与广搜(BFS)

深搜

过程:

对每一个可能的分支路径深入到不能再深入为止。而且每个节点只能访问一次

【第一题:孙悟空找师傅】

问题描述:西游路上咱们的唐长老又一次被妖怪抓走了。已知妖怪洞穴是一个N*N 的正方形,其中有一些假山堵路。
输入:第一行是一个正整数N(2 输出:如果悟空和八戒可以救出师傅就输出YES,否则就输出NO。
样例输入:

4
0 0 0 0
0 1 0 1
1 0 0 1
1 1 0 2

样例输出:

YES

//递归的思想,在二维的数组里面遍历上下左右四个方向

#include
using namespace std;
/*
4
0 0 0 0 
0 1 0 1
1 0 0 1
1 1 0 2
*/
//深搜,孙悟空在地图的左上角,师傅所在的地方为2,
//有石头的地方为1,有路的地方为0,,请输入一个n,以及地图
//寻找孙悟空是否能够找到师傅,可以输出YES,否则输出NO
 
int dx[5]={-1,0,1,0},dy[5]={0,1,0,-1};//控制搜索方向
								//确保四个方向能够搜到 
int G[105][105],vis[105][105];  //G存储地图,
								//vis标记是否搜索过 
int n;//n为地图的长和宽 
bool f=false;//标记是否能够找到师傅 
void dfs(int x,int y){//如果找到师傅则结束 
	if(G[x][y]==2){
		cout<=0&&xx=0&&yy>n;
	for(int i=0;i>G[i][j];
		}
	}
	if(G[0][0]==1){
		cout<<"NO"<

【第二题:传送门】

问题描述:

观音有一件法宝,叫做传送门,我们可以通过这件法宝从妖怪洞穴出去,了保密,观音把这件法宝放在了一个妖怪洞穴,我们只要找到那个洞穴就可以出去了。观音已经把放法宝洞穴的坐标告诉我了,我们需要编程确定一下是否能到达那个洞穴就行了。唐老大:空空,听紧箍咒和编程你选一个吧。空空:你.(吐血三升),你把样例先告诉我。

输入:第一行包含一个正整数N(1

输入:如果悟空他们可以成功走到传送门空间就输出YES,否则就输出 No。

样例输入:

5
1 0 0 1 0
1 1 1 1 1
1 0 1 0 0
1 0 1 1 1
0 1 0 1 0
4 4
2 1

样例输出:

YES
#include
using namespace std;
//输入一个地图,1为可走,0为不可走,下面输入孙悟空所在的坐标
//以及传送门所在的坐标,深度优先搜索看孙悟空是否能找到传送门 
/*
输入:1
5
1 0 0 1 0
1 1 1 1 1
1 0 1 0 0
1 0 1 1 1 
0 1 0 1 0  
4 4 
2 1
输出:
YES
*/
int dx[5]={-1,0,1,0},dy[5]={0,1,0,-1};//遍历方向 
int n;//存储地图
int G[1001][1001],vis[1001][1001];//G存储地图,vis标记是否被搜索过
bool f=false;//存储是否找到传送门 
int sx,sy,cx,cy;
void dfs(int x,int y){
	if(x==cx&&y==cy){
		cout<<"YES"<=1&&xx<=n&&yy>=1&&yy<=n&&G[xx][yy]!=0&&vis[xx][yy]==0){
			vis[xx][yy]=1;
			dfs(xx,yy);
			vis[xx][yy]=0;
		}
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>G[i][j];
		}
	}
	cin>>sx>>sy;
	cin>>cx>>cy;
	if(sx==cx&&cy==sy){
		cout<<"YES"<

【题目三:西游记之海域分块】

问题描述:

最近天气炎热,人鱼王国水位下降陆地露出海面,把王国分成了几个部分,国王的命令无法传达给公民,让红烧鱼国王感觉非常苦恼,所以国王想要请悟空帮忙给各个水域传递一个消息。虽然人鱼王国不大,但是如果悟空每个地方都去一次就会耽误很长时间,影响取经大业,所以悟空决定先计算一下陆地把人鱼王国分成了几部分。输入:第一行包合两个正整数N和M(1

样例输入:

5 5 
1 0 0 1 0
0 1 0 0 1
1 0 1 0 0
1 0 0 1 1
0 1 0 1 0

样例输出:

6


核心思路:
从第一行开始从左向右开始遍历,如果当前位置是0,就从当前位置开始向四周深搜,把相连的0都变成1

#include
using namespace std;
/*
输入:第一行包含两个正整数N和M表示人鱼王国的长和宽 ,下面是一个
N行M列的二维数组,其中1表示陆地,0表示海水 
输出:一个整数a表示陆地把海域分成的份数(斜着方向不算通) 
样例输入:
5 5 
1 0 0 1 0
0 1 0 0 1
1 0 1 0 0
1 0 0 1 1
0 1 0 1 0
样例输出:
6 
*/

//核心思路:从第一行开始,从左向右开始遍历,如果当前位置是0,
          //就从当前位置开始向四周深搜,把相连的 0都变成 1 

int n,m;
int G[1001][1001];
int dx[5]={1,0,-1,0},dy[5]={0,1,0,-1};
void dfs(int x,int y){
	for(int i=0;i<4;i++){
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx>=0&&xx=0&&yy>n>>m;
	for(int i=0;i>G[i][j];
		}
	}
	int res=0;
	for(int i=0;i

【题目三: 国王的神器 】

问题描述:

红烧鱼国王拿出了祖传神器(水管),他可以使斜对角的海域连通,这样悟空就可以少通知一些地方了,真是个不错东西,我们-起来计算一下使用神器后,悟空需要通知几个海域。
输入:第一行包含两个正整数N和M(1 一个N行M列的二维数组,其中1表示陆地,0表示海水。


输入:一个整数a表示陆地把海域分成的份数(斜着方向连通)。
样例输入:

5 5 
1 0 0 1 0
0 1 0 0 1
1 0 1 0 0
1 0 0 1 1
0 1 0 1 0


样例输出:
 

2

#include
using namespace std;
/*
5 5 
1 0 0 1 0
0 1 0 0 1
1 0 1 0 0
1 0 0 1 1
0 1 0 1 0
*/
int G[1001][1001];
int n,m,mins=2147483647,sum=0;
int dx[5]={0,1,0,-1},dy[5]={1,0,-1,0};
void dfs(int x,int y){
	for(int dx=-1;dx<=1;dx++){
		for(int dy=-1;dy<=1;dy++){
			int xx=x+dx;
			int yy=y+dy;
			if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&G[xx][yy]==0){ 
				G[xx][yy]=1;
				dfs(xx,yy);
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>G[i][j];
		}
	}
	int res=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(G[i][j]==0){
				if(G[i][j]==0){
					G[i][j]=1;
					dfs(i,j);
					res++; 
				}
			}
		} 
	}
	cout<

广搜

特点:

BFS是从进到远搜索的,因此通常可以利用BFS来搜索最短的步数

搜索过程:

首先需要把起点给压到队列里面去,接着每一轮判断队列是否为空,如果为空则结束BFS,不为空则取出队首元素a,将所有与a相邻的点判断是否被访问过,如果没有就压进队列中。(按层遍历,找到即最优,并且通常需要通过队列来实现)

#include
using namespace std;
/*
5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 1
0 0 0 1
1 1 4 3 

*/ 
int map[51][51],book[51][51];//map存储地图,book存储是否被标记过 
int m,n,sx,sy,p,q,tx,ty;//m行n列sx,sy表示悟空的坐标,p,q表示师傅所在的坐标
		                 //tx和ty记录中间步骤坐标 
int head=1,tail=1,flag=0;//head表示队首,tail表示队尾,flag标记是否找到师傅 
int nt[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//遍历上下左右四个方向 
struct node{
	int x,y,step;
}que[2501];//定义结构体数组存储当前搜索的x和y以及步数 
void bfs(){
	//记录起点位置 
	que[tail].x=sx;
	que[tail].y=sy;
	que[tail].step=0;
	tail++;//队尾后移 
	book[sx][sy]=1;//标记已走过
	//开始循环搜索 
	while(headm||ty>n) continue;
			//判断该坐标是否可走 
			if(map[tx][ty]==0&&book[tx][ty]==0){
				book[tx][ty]=1;//标记已经走过
				//当前点入队 
				que[tail].x=tx;
				que[tail].y=ty;
				que[tail].step=que[head].step+1;
				tail++; //队尾后移 
			} 
		}
		//判断是否可以找到师傅 
		if(tx==p&&ty==q){//成功找到师傅 
			flag=1;
			break;
		}
		if(flag) break;//找到师傅,停止搜索 
		head++;//队首后移,继续搜索 
	}
}
int main(){
	cin>>m>>n; 
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			cin>>map[i][j];
		}
	}
	cin>>sx>>sy>>p>>q;
	bfs();
	cout<

你可能感兴趣的:(c++,深度优先,宽度优先,算法)