Children of the Candy Corn POJ - 3083(附上只用bfs的做法)

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;
}


转载于:https://www.cnblogs.com/Levi-0514/p/9042489.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值