很好玩的一个游戏,建议大家做完了去玩一玩~。
方块的状态有3种情况,竖着,横躺着,竖躺着,所以可以用一个标记变量表示。
对于判重,可以开一个三维的数组来判断。
麻烦的地方在于移动,如果直接模拟的话,将会产生很大的代码量。250~300行左右……
可以开几个辅助数组,直接判断上下左右时相应的坐标变化。
写辅助数组时最好头脑清醒,写错了某个的话,debug都很困难。。。(可以注意上下的对称性)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
char map[505][505];
int endx,endy;
struct node
{
int dis;
int flag; //0=竖着,1=横躺着,2=竖躺着
int x1;
int y1;
int x2;
int y2;
}start;
node q[1000000];
bool vis[505][505][3];
int dx1[3][4]={{-2,1,0,0},{-1,1,0,0},{-1,2,0,0}};
int dy1[3][4]={{0,0,-2,1},{0,0,-1,2},{0,0,-1,1}};
int ddx[4]={-1,1,0,0};
int ddy[4]={0,0,-1,1};
int dx2[3][4]={{-1,2,0,0},{-1,1,0,0},{-2,1,0,0}};
int dy2[3][4]={{0,0,-1,2},{0,0,-2,1},{0,0,-1,1}};
int c[3][4]={{2,2,1,1},{1,1,0,0},{0,0,2,2}};
int n,m;
bool f(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<m;
}
bool isok(node &t)
{
if(!f(t.x1,t.y1)||!f(t.x2,t.y2)) return false;
if(t.flag==0&&map[t.x1][t.y1]=='E') return false;
if(map[t.x1][t.y1]=='#'||map[t.x2][t.y2]=='#') return false;
return true;
}
void creat()
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(map[i][j]=='O')
{
endx=i;endy=j;
}
else if(map[i][j]=='X')
{
start.x2=start.x1=i;start.y2=start.y1=j;
int rx=i+ddx[3],ry=j+ddy[3];
int dx=i+ddx[1],dy=j+ddy[1];
if(f(rx,ry)&&map[rx][ry]=='X')
{
start.flag=1;
start.x2=rx;start.y2=ry;
map[i][j]=map[rx][ry]='.';
}
else if(f(dx,dy)&&map[dx][dy]=='X')
{
start.flag=2;
start.x2=dx;start.y2=dy;
map[i][j]=map[dx][dy]='.';
}
else
{
start.flag=0;
map[i][j]='.';
}
}
}
start.dis=0;
}
bool expend(node &t,int d)
{
t.x1+=dx1[t.flag][d];
t.y1+=dy1[t.flag][d];
t.x2+=dx2[t.flag][d];
t.y2+=dy2[t.flag][d];
t.dis++;
t.flag=c[t.flag][d];
if(!isok(t)) return false;
if(!vis[t.x1][t.y1][t.flag])
{
vis[t.x1][t.y1][t.flag]=1;
return true;
}
return false;
}
void bfs()
{
int rear=0,front=0;
q[rear++]=start;
node f,r;
while(front<rear)
{
f=q[front];
for(int d=0;d<4;d++)
{
r=f;
if(expend(r,d))
{
q[rear++]=r;
if(r.x1==endx&&r.y1==endy&&r.flag==0)
{
printf("%d\n",r.dis);
return;
}
}
}
front++;
}
printf("Impossible\n");
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m) break;
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
}
memset(vis,0,sizeof(vis));
creat();
bfs();
}
return 0;
}
900多ms很不满意,直接把原代码改成了双搜,竟然还是800多ms。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
char map[505][505];
int endx,endy;
struct node
{
int dis;
int flag; //0=竖着,1=横躺着,2=竖躺着
int x1;
int y1;
int x2;
int y2;
}start,end;
node q1[1000000];
node q2[1000000];
int vis[505][505][3];
int vis2[505][505][3];
int dx1[3][4]={{-2,1,0,0},{-1,1,0,0},{-1,2,0,0}};
int dy1[3][4]={{0,0,-2,1},{0,0,-1,2},{0,0,-1,1}};
int ddx[4]={-1,1,0,0};
int ddy[4]={0,0,-1,1};
int dx2[3][4]={{-1,2,0,0},{-1,1,0,0},{-2,1,0,0}};
int dy2[3][4]={{0,0,-1,2},{0,0,-2,1},{0,0,-1,1}};
int c[3][4]={{2,2,1,1},{1,1,0,0},{0,0,2,2}};
int n,m;
bool f(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<m;
}
bool isok(node &t)
{
if(!f(t.x1,t.y1)||!f(t.x2,t.y2)) return false;
if(t.flag==0&&map[t.x1][t.y1]=='E') return false;
if(map[t.x1][t.y1]=='#'||map[t.x2][t.y2]=='#') return false;
return true;
}
void creat()
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(map[i][j]=='O')
{
endx=i;endy=j;
end.x1=end.x2=i;
end.y1=end.y2=j;
end.flag=0;
end.dis=0;
}
else if(map[i][j]=='X')
{
start.x2=start.x1=i;start.y2=start.y1=j;
int rx=i+ddx[3],ry=j+ddy[3];
int dx=i+ddx[1],dy=j+ddy[1];
if(f(rx,ry)&&map[rx][ry]=='X')
{
start.flag=1;
start.x2=rx;start.y2=ry;
map[i][j]=map[rx][ry]='.';
}
else if(f(dx,dy)&&map[dx][dy]=='X')
{
start.flag=2;
start.x2=dx;start.y2=dy;
map[i][j]=map[dx][dy]='.';
}
else
{
start.flag=0;
map[i][j]='.';
}
}
}
start.dis=0;
}
bool expend(node &t,int d)
{
t.x1+=dx1[t.flag][d];
t.y1+=dy1[t.flag][d];
t.x2+=dx2[t.flag][d];
t.y2+=dy2[t.flag][d];
t.dis++;
t.flag=c[t.flag][d];
if(!isok(t)) return false;
return true;
}
void bfs()
{
int rear1=0,front1=0;
q1[rear1++]=start;
int rear2=0,front2=0;
q2[rear2++]=end;
node f1,r1,f2,r2;
int k1=1,kk1=0,k2=1,kk2=0;
while(front1<rear1&&front2<rear2)
{
while(k1--){
f1=q1[front1];front1++;
for(int d=0;d<4;d++)
{
r1=f1;
if(expend(r1,d))
{
if(vis2[r1.x1][r1.y1][r1.flag])
{
if(vis2[r1.x1][r1.y1][r1.flag]==-1)
vis2[r1.x1][r1.y1][r1.flag]=0;
printf("%d\n",r1.dis+vis2[r1.x1][r1.y1][r1.flag]);
return;
}
if(!vis[r1.x1][r1.y1][r1.flag])
{
vis[r1.x1][r1.y1][r1.flag]=r1.dis;
q1[rear1++]=r1;
kk1++;
}
}
}
}
k1=kk1;kk1=0;
while(k2--)
{
f2=q2[front2];front2++;
for(int d=0;d<4;d++)
{
r2=f2;
if(expend(r2,d))
{
if(vis[r2.x1][r2.y1][r2.flag])
{
if(vis[r2.x1][r2.y1][r2.flag]==-1)
vis[r2.x1][r2.y1][r2.flag]=0;
printf("%d\n",r2.dis+vis[r2.x1][r2.y1][r2.flag]);
return;
}
if(!vis2[r2.x1][r2.y1][r2.flag])
{
vis2[r2.x1][r2.y1][r2.flag]=r2.dis;
q2[rear2++]=r2;
kk2++;
}
}
}
}
k2=kk2;
kk2=0;
}
printf("Impossible\n");
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m) break;
for(int i=0;i<n;i++)
{
scanf("%s",map[i]);
}
memset(vis,0,sizeof(vis));
memset(vis2,0,sizeof(vis2));
creat();
vis2[end.x1][end.y1][end.flag]=-1;
vis[start.x1][start.y1][start.flag]=-1;
bfs();
}
return 0;
}