light oj 1055-Going Together
题目大致意思:
简单的三个棋子,每次可以下达一个命令,robots全部按照指令进行前进;若下一步不为空地则停留在原地。
特殊考虑:
1.例如ABC.....,(或者AB#...C——C需要再次向左移动,AB则不能再次移动)A已经在边界上;这时命令三个棋子全部向左前进,AB就挤到了一块去——然后依次撤回到上一步初始的now状态,至少跑两次循环!
2.或者,ABC每次移动单个棋子时,先首先预判 移动的地方是否有空闲位置!注意ABC连在一块就当不存在处理,因为ABC在一块向左向右都OK可以动!
特别注意:
A single command will be activated for the three robots simultaneously.(因为理解错了题意,当成三个旗子可以随意朝向而不是统一朝向!看我下一篇博客,泪~~)
/* //下面 极大值测试 9 AB....C.. ......... ......... ......... ......... ......... ......... ......... X..X..X.. */ #include<stdio.h> #include<math.h> #include<iostream> #include<string.h> #include<vector> #include<queue> #include<algorithm> using namespace std; #define N 10 #define inf 0x3f3f3f3f char mp[N][N]; int n; struct node{ int x,y; }; struct group{//一个局面三个点的位置,位置之间等价 node p[3];//0,1,2三位有效存储 int step; }st; int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0} }; bool vis[N][N][N][N][N][N];//标记数组,模拟每一组棋子组合成的局面 bool judge_end(group x){ //判断当前局面是否达到结束要求 int num=0; for(int i=0;i<3;i++){ if(mp[x.p[i].x][x.p[i].y]==‘X‘) num++; } if(num==3)return true; return false; } bool judge_node(node a){ if(a.x>=0&&a.y>=0&&a.x<n&&a.y<n&&mp[a.x][a.y]!=‘#‘) return true; return false; } void getvis(group a){//从一个局面获取1个标记即可,剩余5个意义不大(这步在下篇博客上意义较大) vis[a.p[0].x][a.p[0].y][a.p[1].x][a.p[1].y][a.p[2].x][a.p[2].y]=true; /* vis[a.p[0].x][a.p[0].y][a.p[2].x][a.p[2].y][a.p[1].x][a.p[1].y]=true; vis[a.p[1].x][a.p[1].y][a.p[0].x][a.p[0].y][a.p[2].x][a.p[2].y]=true; vis[a.p[1].x][a.p[1].y][a.p[2].x][a.p[2].y][a.p[0].x][a.p[0].y]=true; vis[a.p[2].x][a.p[2].y][a.p[1].x][a.p[1].y][a.p[0].x][a.p[0].y]=true; vis[a.p[2].x][a.p[2].y][a.p[0].x][a.p[0].y][a.p[1].x][a.p[1].y]=true;*/ } void debug(group a){ printf("*%dstep* *A*(%d,%d) ",a.step,a.p[0].x,a.p[0].y); printf("*B*(%d,%d) ",a.p[1].x,a.p[1].y); printf("*C*(%d,%d)\n",a.p[2].x,a.p[2].y); } bool cmp(node a,node b){ return (a.x==b.x)&&(a.y==b.y); } int bfs(){ memset(vis,false,sizeof(vis)); group now,ne; queue<group>Q; st.step=0; Q.push(st); //标记起点局面 getvis(st); while(Q.size()){ now=Q.front(); Q.pop(); if(judge_end(now))return now.step; for(int i=0;i<4;i++){//四种命令的走法 node p1,p2,p3; p1.x=now.p[0].x+dir[i][0]; p1.y=now.p[0].y+dir[i][1]; p2.x=now.p[1].x+dir[i][0]; p2.y=now.p[1].y+dir[i][1]; p3.x=now.p[2].x+dir[i][0]; p3.y=now.p[2].y+dir[i][1]; ne=now;//初始化 if(judge_node(p1))//p1p2p3表示的下一位置,合法则移动 ne.p[0]=p1; if(judge_node(p2)) ne.p[1]=p2; if(judge_node(p3)) ne.p[2]=p3; //一个格点上只能站一个人,站的人多于一个了,就撤回去 for(int j=3;j>=0;j--){ if(cmp(ne.p[0],ne.p[1])||cmp(ne.p[0],ne.p[2])) ne.p[0]=now.p[0]; if(cmp(ne.p[1],ne.p[0])||cmp(ne.p[1],ne.p[2])) ne.p[1]=now.p[1]; if(cmp(ne.p[2],ne.p[0])||cmp(ne.p[2],ne.p[1])) ne.p[2]=now.p[2]; } if(vis[ne.p[0].x][ne.p[0].y][ne.p[1].x][ne.p[1].y][ne.p[2].x][ne.p[2].y]) continue;//已经标记过的 else getvis(ne); ne.step=now.step+1; // debug(ne); if(judge_end(ne))return ne.step; else Q.push(ne); } } return -1; } int main() { int T,cas=0; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=0;i<n;i++)//读图 scanf("%s",mp[i]); int num1=0; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(mp[i][j]>=‘A‘&&mp[i][j]<=‘C‘) st.p[num1].x=i,st.p[num1++].y=j; } } printf("Case %d: ",++cas); int ans=bfs(); if(ans!=-1) printf("%d\n",ans); else printf("trapped\n"); } return 0; }