【lightoj-1055】Going Together(BFS)
链接:http://www.lightoj.com/volume_showproblem.php?problem=1055
类似推箱子的游戏,一条命令可以让abc三个小人同时移动,但是出界或者撞墙是不移动的,求abc到达终点x所需要的最小步数。
我这里用六维的vis来标记这个点走过没,直接上代码
#include<bits/stdc++.h>
using namespace std;
int n;
char mp[12][12];
bool vis[12][12][12][12][12][12];
struct node
{
int ax, ay, bx, by, cx, cy, step;
};
node s;
int bfs()
{
int nx[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
queue<node>Q;
s.step = 0;
Q.push(s);
while(!Q.empty())
{
s = Q.front();
Q.pop();
if(mp[s.ax][s.ay]=='X'&&mp[s.bx][s.by]=='X'&&mp[s.cx][s.cy]=='X') return s.step;
for(int i = 0; i < 4; i++)
{
node t;
t.ax = s.ax + nx[i][0], t.bx = s.bx + nx[i][0], t.cx = s.cx + nx[i][0];
t.ay = s.ay + nx[i][1], t.by = s.by + nx[i][1], t.cy = s.cy + nx[i][1];
if(t.ax<0||t.ax>=n) t.ax = s.ax;
if(t.ay<0||t.ay>=n) t.ay = s.ay;
if(t.bx<0||t.bx>=n) t.bx = s.bx;
if(t.by<0||t.by>=n) t.by = s.by;
if(t.cx<0||t.cx>=n) t.cx = s.cx;
if(t.cy<0||t.cy>=n) t.cy = s.cy;
for(int j = 1; j <= 3; j++) //这里循环3是因为不能让3个小人重合,若循环1次因为走位的次序不同可能还会重合
{
if(mp[t.ax][t.ay]=='#'||(t.ax==t.bx&&t.ay==t.by)||(t.ax==t.cx&&t.ay==t.cy)) t.ax=s.ax, t.ay=s.ay;
if(mp[t.bx][t.by]=='#'||(t.bx==t.ax&&t.by==t.ay)||(t.bx==t.cx&&t.by==t.cy)) t.bx=s.bx, t.by=s.by;
if(mp[t.cx][t.cy]=='#'||(t.cx==t.bx&&t.cy==t.by)||(t.cx==t.ax&&t.cy==t.ay)) t.cx=s.cx, t.cy=s.cy;
}
if(vis[t.ax][t.ay][t.bx][t.by][t.cx][t.cy]) continue;
vis[t.ax][t.ay][t.bx][t.by][t.cx][t.cy] = 1;
t.step = s.step+1;
Q.push(t);
}
}
return -1;
}
int main()
{
int cas = 0, t;
cin>>t;
while(t--)
{
scanf("%d", &n);
memset(vis, 0, sizeof vis);
for(int i = 0; i < n; i++)
scanf("%s", mp[i]);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(mp[i][j] == 'A')
s.ax = i, s.ay = j;
if(mp[i][j] == 'B')
s.bx = i, s.by = j;
if(mp[i][j] == 'C')
s.cx = i, s.cy = j;
}
vis[s.ax][s.ay][s.bx][s.by][s.cx][s.cy] = 1;
printf("Case %d: ", ++cas);
int ans = bfs();
if(ans==-1) puts("trapped");
else printf("%d\n", ans);
}
return 0;
}