P1649 [USACO07OCT] Obstacle Course S题解(BFS洪水填充算法)

如题

题目大意

有一张长宽是 \(n\) 的图,现在要从字符 \(A\) 到字符 \(B\)。其中 \(x\) 则是障碍,问载行走的过程中最少 \(90\) 度转弯多少次。

思路

易错点

这道题有一个坑那就是先搜到的路不一定是转弯转的最少的。

常规思路

按照常规的思路因为这道题需要求路径,所以用BFS的话,就必须要搜完才行。如此一来,时间肯定得超。

优化

这里就涉及到一个民间算法叫洪水填充(不知道哪一位dalao取得名)。

具体思路就是每次选4个方向,看每个方向走到头还是否能走(不能,即四个方向都被堵完),如果能走那么就又将这个点作为起点向外继续拓展,同时打标记(即判重)。

判转弯的话就在每次拓展时加一就行了。

当所有的路径都被拓展到不能拓展时,就判断终点有没有被拓展过,有则输出转弯次数,否则输出-1。

例如

step.1

. . . x . . . .
. . . . . x . .
. . . . . . . .
. . . A . . . .
x . . . . . . x
. . . . . . x x
. . x . . . . .

step.2

. . . x . . . .
. . . * . x . .
. . . * . . . .
* * * A * * * *
x . . * . . . x
. . . * . . x x
. . x * . . . .

step.3

* . . x . . . *
* . . * . x . *
* . . * . . . *
* * * A * * * *
x . . * . . . x
* * * * . . x x
. . x * * * * *

......

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{int x,y;}c[10010];
char s;
int n,ex,ey,xx[]={0,1,0,-1},yy[]={1,0,-1,0},way[110][110];//wey是记录转弯次数
int mp[110][110];
void bfs(){
	int cl=1,op=1;
	while(cl<=op){
		for(int i=0;i<4;i++){
			for(int k=1;;k++){//枚举一个k向外持续拓展
				int tx=c[cl].x+xx[i]*k,ty=c[cl].y+yy[i]*k;
				if(tx>n||tx<1||ty>n||ty<1) break;
				if(mp[tx][ty]==1) break;
				mp[tx][ty]=1;//因为走过已经不能再走了,所以只需要当障碍处理
				way[tx][ty]=way[c[cl].x][c[cl].y]+1;//次数加一
				c[++op].x=tx,c[op].y=ty;
			}
		}
		cl++;
	}
	if(mp[ex][ey]!=0) cout<<way[ex][ey]-1;
		else cout<<-1;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			cin>>s;
			if(s=='A'){c[1].x=i,c[1].y=j;}
			if(s=='B'){ex=i,ey=j;}
			if(s=='x') mp[i][j]=1;
		}
	mp[c[1].x][c[1].y]=1;
	bfs();
	return 0;
}
posted @ 2024-02-20 18:07  Arthur_Douglas  阅读(61)  评论(1编辑  收藏  举报