哈理工oj 2239 影子模仿术【图搜】【BFS+标记方向】

影子模仿术
Time Limit: 500 MS Memory Limit: 32768 K
Total Submit: 62(15 users) Total Accepted: 16(14 users) Rating:  Special Judge: No
Description

鹿丸看见了一个胖子。

“胖子!”

“啊?”

胖子转身,面对面发现站着的鹿丸。奇怪之于,他突然发现自己的脚动不了了。原来他中了鹿丸的影子模仿术。

“你想干嘛?”胖子怒吼。

“我想采访你一下,来,过来”。说着,鹿丸向前走去。胖子发现自己的行动被鹿丸控制了,鹿丸向前走,他也向前走。鹿丸左转,他也左转。

“叫我过去就过去?”胖子一生气,只听见duang的一声,天崩地裂,凭空从地上出现几座大山,不能通行。而此时,胖子和鹿丸的位置也被震的发生了变化,但是影子模仿术没被解除。此时两人一人面向东方,一人面向西方。

鹿丸不料胖子有这等能耐。不过这下可费神了,怎么走到胖子旁边呢?鹿丸往前走,胖子也会往前走,鹿丸不能往一个障碍物前进,但如果鹿丸前进时,胖子前进的位置是障碍物,那么胖子会狠狠的撞上去,不过实际的位置并不会变化。注意,这里说的前是相对的,两人面向何方,那么前就是何方。当然,无论何时,鹿丸只要转向,胖子也会跟着转。

但是现在地形这么复杂,鹿丸需要思考一下,要怎么走才能用最少的步数让自己和胖子走到同一个地方,或者相邻也可以。毕竟和胖子挤一个地方还是挺憋屈的。
Input
多组测试数据
每组测试数据第一行有两个数N,M (2<= N <= 20, 2 <= M <= 20) 表示场地的大小。
接下来有N行,每行有M个字符。描述场地的状态。其中'X'表示障碍,'P'表示胖子,'L'表示鹿丸。
Output
对于每组数据,输出最小的总步数。如果不能相见,则输出"Smart PangZi!"
Sample Input
3 3
PXL
...
...
3 3
PX.
...
.XL
Sample Output
3
2
Hint

多提供几组样例数据

Input:

3 3

P..

L..

...

3 3

XPX

L..

...

3 3

PXL

.X.

...

3 3

PX.

..X

L..


Output:

0

1

5

1

Source
哈尔滨理工大学第五届ACM程序设计竞赛(热身)

首先请各位童鞋切记一句话,不要搞混了P和L,千万不要觉得P和L谁找谁都一样,千万不要以为,以为是一个很蛋疼的形容词,无论是源于你的自信还是源于你的忧伤,请切记,不要以为什么,就是什么。【我搞混了P和L,wa了好几个小时、、、】

我嘴笨,如果口述部分大家看不懂,直接对应代码分析即可

题目分析:图搜题,BFS相对容易很多。标记方向是难点。

难点分析:P随着L转向而转向,我们可以这样处理:

用一个二维数组表示图搜的走路方式,无非一共十六种,面朝南四种走法,面朝北四种走法,东西同理,一共十六种方法,因为P随着L转向而转向,我们大可这样来做:

例如fx【控制当前面朝方向】【以当前面朝方向为基准,0,1,2,3分别代表向前走,向右走,向后走,向左走】、这里我们对应数据一眼就能看懂:

int fx[4][4]={{-1,0,1,0},{0,1,0,-1},{1,0,-1,0},{0,-1,0,1}};
int fy[4][4]={{0,1,0,-1},{1,0,-1,0},{0,-1,0,1},{-1,0,1,0}};

解决掉了标记方向的问题,我们还要防止死循环队列的出现,我们要用数组标记什么情况走过了,因为是两个人四个元素,我们用四维数组vis【】【】【】【】来搞定这个问题:

int vis[26][26][26][26];

然后我们来确定结构体中元素:
struct zuobiao
{
    int cur;//L的方向
    int x,y;//L的位子
    int output;
    int lx,ly;//L控制的P的位子、
    int lcur;//L控制的P的方向
}now,nex;

其他细节问题这里我们对应代码来看、

我们这个时候只需要确定好这五个元素的值,我们就能搞定BFS的操作,AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct zuobiao
{
    int cur;
    int x,y;
    int output;
    int lx,ly;
    int lcur;
}now,nex;
char a[26][26];
int vis[26][26][26][26];
int fx[4][4]={{-1,0,1,0},{0,1,0,-1},{1,0,-1,0},{0,-1,0,1}};
int fy[4][4]={{0,1,0,-1},{1,0,-1,0},{0,-1,0,1},{-1,0,1,0}};
//0 1 2 3 bei dong nan xi
//0 1 2 3 qian you hou zuo
//qian you hou zuo
int n,m;
int check(int x,int y,int xx,int yy)
{
    if(x>=0&&x<n&&y>=0&&y<m&&xx>=0&&xx<n&&yy>=0&&yy<m&&vis[x][y][xx][yy]==0&&a[x][y]!='X')
    {
        return 1;
    }
    return 0;
}
int check2(int x,int y,int xx,int yy)
{
    if(x==xx&&y==yy)
    {
        return 1;
    }
    for(int i=0;i<4;i++)
    {
        int nexx=x+fx[0][i];
        int nexy=y+fy[0][i];
        if(nexx==xx&&nexy==yy)
        return 1;
    }
    return 0;
}
void bfs(int x,int y,int xx,int yy)
{
    memset(vis,0,sizeof(vis));
    now.output=0;
    now.cur=3;
    now.lcur=1;
    now.x=x;
    now.y=y;
    now.lx=xx;
    now.ly=yy;
    vis[x][y][xx][yy]=1;
    queue<zuobiao >s;
    s.push(now);
    while(!s.empty())
    {
        now=s.front();
        if(check2(now.x,now.y,now.lx,now.ly)==1)
        {
            printf("%d\n",now.output);
            return ;
        }
        s.pop();
        for(int i=0;i<4;i++)
        {
            //now.cur
            nex.x=now.x+fx[now.cur][i];
            nex.y=now.y+fy[now.cur][i];
            nex.lx=now.lx+fx[now.lcur][i];
            nex.ly=now.ly+fy[now.lcur][i];
            if(i==0)//向前走方向不变
            {
                nex.cur=now.cur;
                nex.lcur=now.lcur;
            }
            if(i==1)//向右拐方向变化情况
            {
                if(now.cur==0)nex.cur=1;if(now.lcur==0)nex.lcur=1;
                if(now.cur==1)nex.cur=2;if(now.lcur==1)nex.lcur=2;
                if(now.cur==2)nex.cur=3;if(now.lcur==2)nex.lcur=3;
                if(now.cur==3)nex.cur=0;if(now.lcur==3)nex.lcur=0;
            }
            if(i==2)//向后走方向变化情况
            {
                if(now.cur==0)nex.cur=2;if(now.lcur==0)nex.lcur=2;
                if(now.cur==1)nex.cur=3;if(now.lcur==1)nex.lcur=3;
                if(now.cur==2)nex.cur=0;if(now.lcur==2)nex.lcur=0;
                if(now.cur==3)nex.cur=1;if(now.lcur==3)nex.lcur=1;
            }
            if(i==3)//向左走方向变化情况
            {
                if(now.cur==0)nex.cur=3;if(now.lcur==0)nex.lcur=3;
                if(now.cur==1)nex.cur=0;if(now.lcur==1)nex.lcur=0;
                if(now.cur==2)nex.cur=1;if(now.lcur==2)nex.lcur=1;
                if(now.cur==3)nex.cur=2;if(now.lcur==3)nex.lcur=2;
            }
            if(!(nex.lx>=0&&nex.lx<n&&nex.ly>=0&&nex.ly<m))//p可以撞墙.....
            {
                nex.lx=now.lx;
                nex.ly=now.ly;
            }
            if(a[nex.lx][nex.ly]=='X')//撞墙.....
            {
                nex.lx=now.lx;
                nex.ly=now.ly;
            }
            if(check(nex.x,nex.y,nex.lx,nex.ly)==1)//如果符合走的条件
            {
                vis[nex.x][nex.y][nex.lx][nex.ly]=1;//这里第一次交的时候忘记了,
                nex.output=now.output+1;
                s.push(nex);
            }
        }
    }
    printf("Smart PangZi!\n");
    return ;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        int st,sy;
        int ex,ey;
        for(int i=0;i<n;i++)
        {
            scanf("%s",a[i]);
            for(int j=0;j<m;j++)
            {
                if(a[i][j]=='L')
                {
                    st=i;
                    sy=j;
                }
                if(a[i][j]=='P')
                {
                    ex=i;
                    ey=j;
                }
            }
        }
        bfs(st,sy,ex,ey);
    }
}











你可能感兴趣的:(hrbust,hrbust,2239,哈理工oj,2239)