POJ 3083 Children of the Candy Corn(bfs+dfs)

Description
给定一个迷宫,S是起点,E是终点,’#’是墙不可走,’.’可以走。先输出左转优先时,从S到E的步数;再输出右转优先时,从S到E的步数;最后输出S到E的最短步数
Input
多组用例,第一行为用例组数T,每组用例第一行为两个整数w和h分别表示迷宫宽度和高度,之后为一h*w矩阵表示迷宫
Output
对于每组用例,先输出左转优先时,从S到E的步数;再输出右转优先时,从S到E的步数;最后输出S到E的最短步数
Sample Input

Sample Output
37 5 5
17 17 9
Solution
dfs求左右转优先的步数,bfs求最短步数
因为从起点右转优先到达终点等价于从终点左转优先到达起点,故只需写一个以左转优先的dfs即可,左转优先时必须标记当前位置的方向,下面是我定义的方向

最初的方向由起点S确定,而下一步的方向则由前一步的走向决定
左边优先搜索:
当前位置的方向指向 1(向左)(这同时说明前一步是在3位置走过来的)
那么走下一步时,就要根据2103的顺序,先逐格确定当前位置周边的四格是否可行
若第一次确认2可行,就走到2,在位置2时的方向为2(向下)
若2不可行,则再确定1,若1可行,就走到1,在位置1时的方向为1(向左)
若1也不可行,则再确定0,若0可行,就走到0,在位置0时的方向为0(向上)
若0也不可行,说明进入了迷宫的死胡同,要从原路返回,走回3
根据定义的方向,设当前位置为d,那么左转用数学式子表达就是 d=(d+1)%4
注意:
左边、右边优先搜索都不是找最短路,因此走过的路可以再走,无需标记走过的格
Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 50
int dd[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
bool vis[maxn][maxn];
char map[maxn][maxn];
int sx,sy,ex,ey;
int T,w,h;
int Count,flag;
struct node
{
    int x,y;
    int dis;
};
void dfs(int x,int y,int tx,int ty,int d)
{
    if(x==tx&&y==ty)//到达终点 
    {
        flag=1;
        return ;
    }
    d=(d+3)%4;//改变方向 
    for(int i=d;i<d+4;i++)//四个方向枚举,注意顺序 
    {
        int xx=x+dd[i%4][0];
        int yy=y+dd[i%4][1];
        if(xx>=0&&xx<h&&yy>=0&&yy<w&&map[xx][yy]!='#')//可以走 
        {
            Count++;//步数加一 
            d=i;//更新方向 
            dfs(xx,yy,tx,ty,d);//继续搜索 
            if(flag)//已到达终点,直接返回 
                return ;
        }
    }
}
void bfs()
{
    queue<node>P;
    node now,temp;
    now.x=sx;
    now.y=sy;
    now.dis=1;
    P.push(now);//起点入队 
    while(!P.empty())
    {
        now=P.front();//出队 
        P.pop();
        if(map[now.x][now.y]=='E')//到达终点 
        {
            cout<<now.dis<<endl;
            return ;
        }
        for(int i=0;i<4;i++)//四个方向枚举 
        {
            temp.x=now.x+dd[i][0];
            temp.y=now.y+dd[i][1];
            temp.dis=now.dis+1;//步数加一 
            if(!vis[temp.x][temp.y]&&temp.x>=0&&temp.x<h&&temp.y>=0&&temp.y<w&&map[temp.x][temp.y]!='#')//可以走 
            {
                vis[temp.x][temp.y]=true;//标记该点 
                P.push(temp);//入队 
            }
        }
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&w,&h);
        for(int i=0;i<h;i++)
        {
            getchar();
            for(int j=0;j<w;j++)
            {
                scanf("%c",&map[i][j]);
                if(map[i][j]=='S')//起点坐标 
                    sx=i,sy=j;
                if(map[i][j]=='E')//终点坐标 
                    ex=i,ey=j;
            }
        }
        flag=0;//标志变量初始化 
        Count=1;//步数初始化 
        dfs(sx,sy,ex,ey,0);//从起点到终点左转优先 
        cout<<Count<<" ";
        flag=0;//标志变量初始化 
        Count=1;//步数初始化 
        dfs(ex,ey,sx,sy,0);//从终点到起点左转优先即为从起点到终点右转优先 
        cout<<Count<<" ";
        memset(vis,false,sizeof(vis));//初始化标记数组 
        bfs();
    }
    return 0;
}

你可能感兴趣的:(POJ 3083 Children of the Candy Corn(bfs+dfs))