1. 程式人生 > >POJ - 3083 Children of the Candy Corn

POJ - 3083 Children of the Candy Corn

Children of the Candy Corn

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 15219   Accepted: 6553

Description

The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombies, chainsaw-wielding psychopaths, hippies, and other terrors on their quest to find the exit. 

One popular maze-walking strategy guarantees that the visitor will eventually find the exit. Simply choose either the right or left wall, and follow it. Of course, there's no guarantee which strategy (left or right) will be better, and the path taken is seldom the most efficient. (It also doesn't work on mazes with exits that are not on the edge; those types of mazes are not represented in this problem.) 

As the proprieter of a cornfield that is about to be converted into a maze, you'd like to have a computer program that can determine the left and right-hand paths along with the shortest path so that you can figure out which layout has the best chance of confounding visitors.

Input

Input to this problem will begin with a line containing a single integer n indicating the number of mazes. Each maze will consist of one line with a width, w, and height, h (3 <= w, h <= 40), followed by h lines of w characters each that represent the maze layout. Walls are represented by hash marks ('#'), empty space by periods ('.'), the start by an 'S' and the exit by an 'E'. 

Exactly one 'S' and one 'E' will be present in the maze, and they will always be located along one of the maze edges and never in a corner. The maze will be fully enclosed by walls ('#'), with the only openings being the 'S' and 'E'. The 'S' and 'E' will also be separated by at least one wall ('#'). 

You may assume that the maze exit is always reachable from the start point.

Output

For each maze in the input, output on a single line the number of (not necessarily unique) squares that a person would visit (including the 'S' and 'E') for (in order) the left, right, and shortest paths, separated by a single space each. Movement from one square to another is only allowed in the horizontal or vertical direction; movement along the diagonals is not allowed.

Sample Input

2
8 8
########
#......#
#.####.#
#.####.#
#.####.#
#.####.#
#...#..#
#S#E####
9 5
#########
#.#.#.#.#
S.......E
#.#.#.#.#
#########

Sample Output

37 5 5
17 17 9

題意:在給定的地圖裡,“#”不能走,“.”可以走,從S出發走到E,要求輸出三個結果,第一個每次走的時候優先向左走,第二個每次走的時候優先向右走,第三個最短路徑。

最短路徑用廣搜就能寫出來,那麼優先左走和優先右走用深搜會好一點,我的方法比較笨,就是寫出了左走和右走兩個函式,我分別開了兩組陣列來寫左走和右走,每次走的時候都用初始方向-1的下一步來表示左或者右。

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
int sx,sy,ex,ey,h,w;
struct node
{
    int x,y,step;
};
int vis[50][50];
char mapp[50][50];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int dlx[4]={0,-1,0,1};//左走,左下右上(每次向左轉)
int dly[4]={-1,0,1,0};
int drx[4]={0,-1,0,1};//右走,右下左上(每次向右轉)
int dry[4]={1,0,-1,0};
int judge(int x,int y)
{
    if(x>=0&&x<h&&y>=0&&y<w&&!vis[x][y]&&mapp[x][y]!='#')
        return 1;
    return 0;
}
int judge1(int x,int y)
{
    if(x>=0&&x<h&&y>=0&&y<w&&mapp[x][y]!='#')
        return 1;
    return 0;
}
int book1,book2;
int bfs()//廣搜不多說就是求最短時間
{
    queue<node>q;
    while(!q.empty())
        q.pop();
    node st,ed;
    st.x=sx;
    st.y=sy;
    st.step=0;
    q.push(st);
    memset(vis,0,sizeof(vis));
    vis[sx][sy]=1;
    while(!q.empty())
    {
        st=q.front();
        q.pop();
        if(st.x==ex&&st.y==ey)
            return st.step;
        for(int i=0;i<4;i++)
        {
            ed.x=st.x+dx[i];
            ed.y=st.y+dy[i];
            if(judge(ed.x,ed.y))
            {
                vis[ed.x][ed.y]=1;
                ed.step=st.step+1;
                q.push(ed);
            }
        }
    }
    return -1;
}
int dfsl(int x,int y,int flag,int step)
{
    if(x==ex&&y==ey)
    {
        book1=1;
        return step;
    }
    if(flag==1)//開始的方向是向下的話,我們後退一步就是左方向的前一個,那麼我們要走下一步就是左方向了
       flag=0;
    else if(flag==2)
        flag=1;
    else if(flag==3)
        flag=2;
    else if(flag==0)
        flag=3;
    for(int i=flag;i<4;i++)
    {
        int xx=x+dlx[i];
        int yy=y+dly[i];
        if(judge1(xx,yy))
           return dfsl(xx,yy,i,step+1);
        if(book1==1)
            break;
        if(i==3)
            i=-1;
    }
}
int dfsr(int x,int y,int flag,int step)//有方向同理於左方向,都是上一個方向的想一個狀態時右轉
{
    if(x==ex&&y==ey)
    {
        book2=1;
        return step;
    }
    if(flag==1)
       flag=0;
    else if(flag==2)
        flag=1;
    else if(flag==3)
        flag=2;
    else if(flag==0)
        flag=3;
    for(int i=flag;i<4;i++)
    {
        int xx=x+drx[i];
        int yy=y+dry[i];
        if(judge1(xx,yy))
           return dfsr(xx,yy,i,step+1);
        if(book2==1)
            break;
        if(i==3)
            i=-1;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&w,&h);
        for(int i=0;i<h;i++)
        {
            scanf("%s",mapp[i]);
            for(int j=0;j<w;j++)
            {
                if(mapp[i][j]=='S')
                    sx=i,sy=j;
                if(mapp[i][j]=='E')
                    ex=i,ey=j;
            }
        }
        book1=0;
        book2=0;
        printf("%d ",dfsl(sx,sy,1,1));
        printf("%d ",dfsr(sx,sy,1,1));
        printf("%d\n",bfs()+1);
    }
}