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.
'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(*).
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.
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.
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.*
*******
*/