Children of the Candy Corn POJ - 3083
点击打开链接
题意:一个有优先级的bfs,输出三个数,先输出优先向左走的步数,然后输出优先向右走的步数,最后输出最短路。
(不过,之后看题解,大佬们都是用dfs加bfs来做,我就给出我bfs的做法,dfs+bfs的大家可以自己去搜)
思路:分三次搜索,第一次优先向左走,第二次优先向右,最后直接最短路
注意:由于前两次不一定是最短路,所以不用标记是否走过,而且,由于是有优先级,可以走的话,就必须先走优先级高的,所以,在判断cango后,如果可行,加入队列后就要break;
还有一个难点就是根据优先级搜索,这里的转向数组dx,dy,tx,ty以及搜索的顺序都需要好好推一下才能发现规律
优先左走时,优先级为,左,上,右,下。优先右走时,优先级为,右,上,左,下。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m;
char Map[50][50];
int ans[50][50];
int vis[50][50];
int sx,sy,ex,ey;
typedef struct man
{
int first,second,face;
}P;
int dx[]={-1,0,1,0};//方向数组
int dy[]={0,-1,0,1};
int tx[]={0,1,0,-1};
int ty[]={-1,0,1,0};
bool cango(int x,int y,int flag)
{
if(x<=0||x>n||y<=0||y>m||Map[x][y]=='#'||(flag==0&&vis[x][y]))
return 0;
return 1;
}
int bfs(int flag,int f)//flag记录优先级,1为向左走的优先级,2为向右走,0为最短路
{
memset(ans,0,sizeof ans);
if(flag==0){
memset(vis,0,sizeof vis);
vis[sx][sy]=1;
}
queue<P> que;
while(!que.empty())
que.pop();
P p;
p.first=sx;
p.second=sy;
p.face=f;
que.push(p);
while(!que.empty()){
p=que.front();
que.pop();
int mx,my,face;
if(p.first==ex&&p.second==ey){
return ans[ex][ey];
}
if(flag==1){
for(int i=4;i>=1;i--){
mx=p.first+dx[(p.face+i)%4];//保证按照优先级搜索的公式,需要自己好好体会一下,在这里,我令1,2,3,4分别代表上左下右
my=p.second+dy[(p.face+i)%4];
face=(p.face+1+i)%4;
if(face==0)
face=4;
if(cango(mx,my,flag)){
ans[mx][my]=ans[p.first][p.second]+1;
P q;
q.first=mx,q.second=my,q.face=face;
que.push(q);
break;//因为有优先级,所以优先级高,并且可走的,一定要走
}
}
}
else if(flag==2){
for(int i=1;i<=4;i++){
mx=p.first+tx[(p.face+i)%4];
my=p.second+ty[(p.face+i)%4];
face=(p.face+2+i)%4;
if(face==0)
face=4;
if(cango(mx,my,flag)){
ans[mx][my]=ans[p.first][p.second]+1;
P q;
q.first=mx,q.second=my,q.face=face;
que.push(q);
break;
}
}
}
else if(flag==0){//迷宫最短路模板
for(int i=0;i<4;i++){
mx=p.first+dx[i];
my=p.second+dy[i];
if(cango(mx,my,flag)){
ans[mx][my]=ans[p.first][p.second]+1;
vis[mx][my]=1;
P q;
q.first=mx,q.second=my,q.face=p.face;
que.push(q);
}
}
}
}
}
int main()
{
int t,face;
scanf("%d",&t);
while(t--){
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++){
getchar();
for(int j=1;j<=m;j++){
scanf("%c",&Map[i][j]);
if(Map[i][j]=='S'){
sx=i,sy=j;
if(Map[i-1][j]=='.')//判断起点朝向,最后我发现不判断好像也没什么问题
face=1;
else if(Map[i][j-1]=='.')
face=2;
else if(Map[i+1][j]=='.')
face=3;
else
face=4;
}
else if(Map[i][j]=='E')
ex=i,ey=j;
}
}
int a=bfs(1,face)+1,b=bfs(2,face)+1,c=bfs(0,face)+1;
printf("%d %d %d\n",a,b,c);
}
return 0;
}