hdu 3309 Roll The Cube【BFS】


Roll The Cube

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 589    Accepted Submission(s): 226


Problem Description
This is a simple game.The goal of the game is to roll two balls to two holes each.
'B' -- ball
'H' -- hole
'.' -- land
'*' -- wall
Remember when a ball rolls into a hole, they(the ball and the hole) disappeared, that is , 'H' + 'B' = '.'.
Now you are controlling two balls at the same time.Up, down , left , right --- once one of these keys is pressed, balls exist roll to that direction, for example , you pressed up , two balls both roll up. 
A ball will stay where it is if its next point is a wall, and balls can't be overlap.
Your code should give the minimun times you press the keys to achieve the goal.
 

Input
First there's an integer T(T<=100) indicating the case number.
Then T blocks , each block has two integers n , m (n , m <= 22) indicating size of the map.
Then n lines each with m characters.
There'll always be two balls(B) and two holes(H) in a map.
The boundary of the map is always walls(*).
 

Output
The minimum times you press to achieve the goal.
Tell me "Sorry , sir , my poor program fails to get an answer." if you can never achieve the goal.
 
Sample Input
4
6 3
***
*B*
*B*
*H*
*H*
***
4 4
****
*BB*
*HH*
****
4 4
****
*BH*
*HB*
****
5 6
******
*.BB**
*.H*H*
*..*.*
******
Sample Output
3
1
2
Sorry , sir , my poor program fails to get an answer.


题目大意:每张地图里边有两个球,用字母B表示,有两个洞,用字母H表示,控制两个球向一个方向移动,问最少步数实现两个球进两个洞。如果做不到,输出Sorry , sir , my poor program fails to get an answer.

思路:对于两个小球,四维判重,对于两个球,如果有一个球已经进洞了,辣么就单单移动另一个球,这里要进行特殊判定。BFS这种图搜题目思路好构建,主要是debug和具体操作,有不慎重的地方就不免会死循环或者是wa,TLE到死,WA到死T__T,样例根本就不够看的好吗T__T
辣么,我们单拿出BFS部分代码进行细节处理:
void bfs()
{
    memset(vis,0,sizeof(vis));
    queue<zuobiao >s;
    now.x[0]=x1;now.x[1]=x2;
    now.y[0]=y1;now.y[1]=y2;//起点
    now.output=0;
    s.push(now);
    vis[now.x[0]][now.y[0]][now.x[1]][now.y[1]]=1;//四维判重
    while(!s.empty())
    {
        now=s.front();
        //printf("%d %d %d %d %d\n",now.x[0],now.y[0],now.x[1],now.y[1],now.output);
        if(a[now.x[0]][now.y[0]]=='H'&&a[now.x[1]][now.y[1]]=='H')//如果两个小球都滚到了洞上边
        {
            if(!(now.x[0]==now.x[1]&&now.y[0]==now.y[1]))//并且这两个小球滚到的不是同一个洞,辣么就达到目标了~
            {
                printf("%d\n",now.output);
                return ;
            }
        }
        s.pop();
        for(int i=0;i<4;i++)//四种走法
        {
            nex=now;
            int f=0;//标记,如果f==1表示已经有一个球进洞了,如果另一个也进洞了并且代码运行到这里说明这两个球进的洞是同一个洞
            for(int j=0;j<2;j++)//对于两个球
            {
                if(a[now.x[j]][now.y[j]]=='H'&&f==0)//如果其中一个已经进洞,就不用管了,如果两个都到了洞,辣么处理另一个,用f标记处理
                {
                    nex.x[j]=now.x[j];
                    nex.y[j]=now.y[j];
                    f=1;continue;
                }
                else
                {
                    nex.x[j]=now.x[j]+fx[i];
                    nex.y[j]=now.y[j]+fy[i];
                }
            }//move
            nex.output=now.output+1;
            if(check(nex.x[0],nex.y[0])||check(nex.x[1],nex.y[1]))//只要有一个球能够走下去(这块的处理是指不出边界并且走到的地方不是墙,只要任意一个球符合能走的情况,就可以走)
            {
                if(check(nex.x[0],nex.y[0])==0){nex.x[0]=now.x[0];nex.y[0]=now.y[0];}
                if(check(nex.x[1],nex.y[1])==0){nex.x[1]=now.x[1];nex.y[1]=now.y[1];}//处理不能走的那个球到原地不动。
                if(vis[nex.x[0]][nex.y[0]][nex.x[1]][nex.y[1]]==0)//如果走到的情况没有走过
                {
                    if(nex.x[0]==nex.x[1]&&nex.y[0]==nex.y[1]&&a[nex.x[0]][nex.y[0]]!='H')continue;//如果两个球重合了并且没有一个球进洞,辣么属于非法操作
                    s.push(nex);
                    vis[nex.x[0]][nex.y[0]][nex.x[1]][nex.y[1]]=1;
                }
            }
        }
    }
    printf("Sorry , sir , my poor program fails to get an answer.\n");
}
然后是完整的AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct zuobiao
{
    int x[2],y[2];
    int output;
}now,nex;
int n,m;
int vis[25][25][25][25];
char a[150][150];
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
int x1,x2,y1,y2;

int check(int x,int y)
{
    if(x>=0&&x<n&&y>=0&&y<m&&a[x][y]!='*')return 1;
    else return 0;
}
void bfs()
{
    memset(vis,0,sizeof(vis));
    queue<zuobiao >s;
    now.x[0]=x1;now.x[1]=x2;
    now.y[0]=y1;now.y[1]=y2;
    now.output=0;
    s.push(now);
    vis[now.x[0]][now.y[0]][now.x[1]][now.y[1]]=1;
    while(!s.empty())
    {
        now=s.front();
        //printf("%d %d %d %d %d\n",now.x[0],now.y[0],now.x[1],now.y[1],now.output);
        if(a[now.x[0]][now.y[0]]=='H'&&a[now.x[1]][now.y[1]]=='H')
        {
            if(!(now.x[0]==now.x[1]&&now.y[0]==now.y[1]))
            {
                printf("%d\n",now.output);
                return ;
            }
        }
        s.pop();
        for(int i=0;i<4;i++)
        {
            nex=now;
            int f=0;
            for(int j=0;j<2;j++)
            {
                if(a[now.x[j]][now.y[j]]=='H'&&f==0)
                {
                    nex.x[j]=now.x[j];
                    nex.y[j]=now.y[j];
                    f=1;continue;
                }
                else
                {
                    nex.x[j]=now.x[j]+fx[i];
                    nex.y[j]=now.y[j]+fy[i];
                }
            }//move
            nex.output=now.output+1;
            if(check(nex.x[0],nex.y[0])||check(nex.x[1],nex.y[1]))//只要有一个球能够走下去
            {
                if(check(nex.x[0],nex.y[0])==0){nex.x[0]=now.x[0];nex.y[0]=now.y[0];}
                if(check(nex.x[1],nex.y[1])==0){nex.x[1]=now.x[1];nex.y[1]=now.y[1];}//处理不能走的那个球到原地不动。
                if(vis[nex.x[0]][nex.y[0]][nex.x[1]][nex.y[1]]==0)
                {
                    if(nex.x[0]==nex.x[1]&&nex.y[0]==nex.y[1]&&a[nex.x[0]][nex.y[0]]!='H')continue;
                    s.push(nex);
                    vis[nex.x[0]][nex.y[0]][nex.x[1]][nex.y[1]]=1;
                }
            }
        }
    }
    printf("Sorry , sir , my poor program fails to get an answer.\n");
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int f=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",a[i]);
            for(int j=0;j<m;j++)
            {
                if(a[i][j]=='B')
                {
                    if(f==0)
                    {
                        x1=i;y1=j;f=1;continue;
                    }
                    else
                    {
                        x2=i;y2=j;
                    }
                }
            }
        }
        bfs();
    }
}
/*
4
7 7
*******
*.....*
*.B.B.*
*.*.*.*
*..*H**
*...H.*
*******
*/










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值