很好玩的一个游戏,建议大家做完了去玩一玩~。
方块的状态有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; }