题意:有一颗n个节点的树,其中一个节点有机器人,指定m个节点有障碍物,指定终点,问最少需要移动多少步才能到达,移动过程中遇到障碍物需要将其移动到空地。
分析:bfs搜索,是每次都对障碍物进行移动,将障碍物移动到空闲地方,如果是机器人移动就需要更新位置。
障碍物位置用二进制储存,方便查找,更新。
# include<iostream>
# include<cstdio>
# include<cmath>
# include<map>
# include<queue>
# include<string>
# include<string.h>
#include<set>
#include<list>
# include<algorithm>
using namespace std;
const int maxn = 1 << 20;
struct node {
int state, pos, pre, len;
node(){}
node(int _state,int _pos,int _pre,int _len):state(_state),pos(_pos),pre(_pre),len(_len){}
};
vector<int>G[20];
node q[maxn];
int vis[20][maxn];
int n, obnum, s, t;
int start,step;
void bfs(int ob) {
int front = 0, rear = 1;
node temp(ob, s, -1, 0);
q[front] = temp;
vis[s][ob] = 1;
while (front < rear) {
node u = q[front];
if (u.pos == t) {//移动到终点就退出
start = front;
step = u.len;
break;
}
for (int i = 0; i < n; i++) {
if ((1 << i)&u.state) {//找到障碍物位置
for (int j = 0; j < G[i].size(); j++) {
int next = G[i][j];
if ((1 << next)&u.state)continue;//找到空闲位置
node ttd = u;
ttd.pos = u.pos; ttd.state = ((u.state|(1<<next))^(1<<i));
if (ttd.pos == i)ttd.pos = next;//如果是机器人移动,就更新位置
if (!vis[ttd.pos][ttd.state]) {
vis[ttd.pos][ttd.state] = 1;
ttd.len++;
ttd.pre = front;
q[rear++] = ttd;
}
}
}
}
front++;
}
}
void result(int u) {
if (q[u].pre != 0)result(q[u].pre);//从前往后输出
int last = q[q[u].pre].state;
int cur = q[u].state;;
int a, b;
a = last ^ (last&cur);//因为每次只移动一步
b = cur ^ (last&cur);
int aa, bb;
for (int i = 0; i < n; i++) {
if ((1 << i)&a)aa = i;
if ((1 << i)&b)bb = i;
}
cout << aa + 1 << " " << bb + 1 << endl;
}
int main() {
int kase;
cin >> kase;
for (int k = 0; k < kase; k++) {
for (int i = 0; i < 20; i++)G[i].clear();
memset(vis, 0, sizeof(vis));
step = -1;
cin >> n >> obnum >> s >> t;
int obstacle = 0;
s--, t--;
for (int i = 0; i < obnum; i++) {
int l;
cin >> l;
l--;
obstacle |= (1<<l);
}
for (int i = 0; i < n - 1; i++) {
int temp,temp1; cin >> temp>>temp1;
G[temp-1].push_back(temp1-1);
G[temp1-1].push_back(temp-1);
}
obstacle |= (1 << s);
bfs(obstacle);
cout << "Case " << k + 1 << ": ";
if (step == -1) {
cout << "-1" << endl;
}
else {
cout << step << endl;
result(start);
}
}
return 0;
}