【Ybt OJ】[基础算法 第5章] 广度搜索 [前半章]

「 「 基础算法 」 」 5 5 5章 广度搜索 ( ( 3 3 3 ) )

后半章 l i n k link link

目录:

A.走迷宫
B.山峰和山谷
C.立体推箱子

A . A. A. 例题 1 1 1 走迷宫

在这里插入图片描述

分析:

屑题一道 b f s bfs bfs模板 具体看代码吧

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#pragma GCC optimize(2)
#define reg register 
using namespace std;
typedef long long ll;
typedef double db;
const int N=1005;
const int M=1000005;
int n,sx,sy,ex,ey;
bool vis[N][N];
int dx[5]={
    
    0,1,0,-1},dy[5]={
    
    -1,0,1,0};
char a[N][N];
struct node{
    
    
	int x,y,step;
}p[M];
bool check(int x,int y)
{
    
    
	if(x>0&&x<=n&&y>0&&y<=n&&!vis[x][y]&&a[x][y]=='0') return true;  //不合法
	else{
    
    return false;}
}
void bfs()  //板子
{
    
    
	int head=0,tail=1;
	p[1].x=sx;p[1].y=sy;
	p[1].step=0;
	while(head<tail)
	{
    
    
		head++;
		for(int i=0;i<4;i++)
		{
    
    
			int xx=dx[i]+p[head].x;
			int yy=dy[i]+p[head].y;
			if(check(xx,yy))
			{
    
    
				tail++;p[tail].step=p[head].step+1;
				p[tail].x=xx;p[tail].y=yy;
				vis[xx][yy]=1;
				if(xx==ex&&yy==ey)
				{
    
    
					printf("%d",p[tail].step);
					return;
				}
			}
		}
	}
}
int main(){
    
    
	scanf("%d",&n);
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=n;j++)
			cin>>a[i][j];
	scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
	bfs();
	
	return 0;
} 

B . B. B. 例题 2 2 2 山谷和山峰

洛谷 l i n k link link
在这里插入图片描述
在这里插入图片描述

分析:

山峰和山谷 即字面意思 中间高四周低中间低四周高
那么开始 b f s bfs bfs 如果搜到的点高度一致 就正常加入 q u e u e queue queue
否则对这个点进行山峰和山谷的判断即可.

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue> 
#pragma GCC optimize(2)
#define reg register 
using namespace std;
typedef long long ll;
typedef double db;
const int N=1005;
struct node{
    
    
	int x,y;
}que[N*N];
int n,a[N][N],vis[N][N],cnt,mount,valley;
int dx[9]={
    
    0,1,0,-1,1,1,-1,-1},dy[9]={
    
    1,0,-1,0,1,-1,1,-1};
void bfs(int sx,int sy)  //广搜
{
    
    
	int head=0,tail=1;
	bool f1=0,f2=0;
	que[1].x=sx;que[1].y=sy;
	while(head<tail)
	{
    
    
		head++;
		for(int i=0;i<8;i++)
		{
    
    
			int xx=dx[i]+que[head].x;
			int yy=dy[i]+que[head].y;
			if(xx<1||xx>n||yy<1||yy>n) continue;
			if(!vis[xx][yy]&&a[xx][yy]==a[que[head].x][que[head].y])
			{
    
    
				vis[xx][yy]=1;
				tail++;
				que[tail].x=xx;
				que[tail].y=yy;
			}
			if(a[xx][yy]>a[que[head].x][que[head].y]) f1=1;  //山谷
			if(a[xx][yy]<a[que[head].x][que[head].y]) f2=1;  //山峰
		}
		
	}
	if(f1&&!f2) valley++;
	if(f2&&!f1) mount++;
}
int main(){
    
    
	scanf("%d",&n);
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=n;j++)
		{
    
    
			if(!vis[i][j])
			{
    
    
				vis[i][j]=1;
				bfs(i,j);
				cnt++;
			}
		} 
	if(cnt==1){
    
    
		printf("1 1");
		return 0;
	}else printf("%d %d",mount,valley);
	return 0;
} 

C . C. C. 例题 3 3 3 立体推箱子

P O J POJ POJ l i n k link link
在这里插入图片描述
在这里插入图片描述

分析:

我们先正常处理起点和终点 然后开始 b f s bfs bfs
要考虑立着 横着 竖着这些状态 以及要对这些状态进行处理 判断可行性
找起点要注意分横竖和立着找 有三种起点
可以用一个 s t r u c t struct struct存储 坐标和当前状态
可以设 0 0 0立着 1 1 1 2 2 2
具体细节看代码吧

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue> 
#pragma GCC optimize(2)
#define reg register 
using namespace std;
typedef long long ll;
typedef double db;
const int N=505;
int n,m,step[N][N][3];
char G[N][N];
struct node{
    
    
	int x,y,qwq;
}st,ed;
int way[4][2]={
    
    0,-1,0,1,-1,0,1,0};
int nex_x[3][4]={
    
    {
    
    0,0,-2,1},{
    
    0,0,-1,1},{
    
    0,0,-1,2}};
int nex_y[3][4]={
    
    {
    
    -2,1,0,0},{
    
    -1,2,0,0},{
    
    -1,1,0,0}};  //三种状态的方向数组
int nex_st[3][4]={
    
    {
    
    1,1,2,2},{
    
    0,0,1,1},{
    
    2,2,0,0}};
bool judge(int x,int y)
{
    
    
	if(x<1||x>n||y<1||y>m){
    
    return false;}
	return true;
}
void get_start_end()
{
    
    
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=m;j++)
		{
    
    
			if(G[i][j]=='O')
			{
    
    
				ed.x=i;ed.y=j;  //终点
				ed.qwq=0;
				G[i][j]='.';
			}
			if(G[i][j]=='X')  //横着竖着都有两个X
			{
    
    
				for(int k=0;k<4;k++)
				{
    
    
					int dx=way[k][0]+i;  //找起点
					int dy=way[k][1]+j;
					if(judge(dx,dy)&&G[dx][dy]=='X')
					{
    
    
						st.x=min(dx,i);
						st.y=min(dy,j);
						st.qwq=(k<2)?1:2;  //0 1是左右,2 3是上下
						//根据这个来看是竖 还是横
						G[i][j]=G[dx][dy]='.';
						break;
					}
				}
				if(G[i][j]=='X')  //初始是立着
				{
    
    
					st.x=i;st.y=j;
					st.qwq=0;  //设为立着状态
					G[i][j]='.';
				}
			}
		}
}
bool check(node p)
{
    
    
	if(!judge(p.x,p.y)){
    
    return false;}
	if(G[p.x][p.y]=='#'){
    
    return false;}
	if(p.qwq==0&&G[p.x][p.y]!='.'){
    
    return false;}  //可行性
	if(p.qwq==1&&G[p.x][p.y+1]=='#'){
    
    return false;}
	if(p.qwq==2&&G[p.x+1][p.y]=='#'){
    
    return false;}
	return true;
}
int bfs()
{
    
    
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=m;j++)
			for(int k=0;k<3;k++)
				step[i][j][k]=-1;
	queue<node> q;
	step[st.x][st.y][st.qwq]=0;
	q.push(st);
	while(!q.empty())
	{
    
    
		node now=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
    
    
			node next;
			next.x=now.x+nex_x[now.qwq][i];
			next.y=now.y+nex_y[now.qwq][i];
			next.qwq=nex_st[now.qwq][i];
			if(check(next)&&step[next.x][next.y][next.qwq]==-1)
			{
    
    
				step[next.x][next.y][next.qwq]=step[now.x][now.y][now.qwq]+1;
				q.push(next);
				if(next.x==ed.x&&next.y==ed.y&&next.qwq==ed.qwq)  //匹配终点
					return step[next.x][next.y][next.qwq];
			}
		}
	}
	return -1;
}
int main(){
    
    
	while(~scanf("%d%d",&n,&m))
	{
    
    
		if(n==0&&m==0) break;
		for(reg int i=1;i<=n;i++)
			for(reg int j=1;j<=m;j++)
				cin>>G[i][j];
		get_start_end();
		//cout<<endl<<ed.x<<" "<<ed.y<<" "<<ed.qwq<<endl; 
		int ans=bfs();
		if(ans!=-1) printf("%d\n",ans);
		else puts("Impossible");
	}	
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/112389887
今日推荐