1. 程式人生 > >【loj-1055-Going Together-三個棋子推箱子走到目的地--講預判的bfs】

【loj-1055-Going Together-三個棋子推箱子走到目的地--講預判的bfs】

題目 step 是否 3.x 單個 size inf AI fin

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; }
View Code

【loj-1055-Going Together-三個棋子推箱子走到目的地--講預判的bfs】