「 「 「基础算法 」 」 」第 5 5 5章 广度搜索 ( ( (前 3 3 3题 ) ) )
目录:
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 山谷和山峰
分析:
山峰和山谷 即字面意思 中间高四周低 或中间低四周高
那么开始 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;
}