bfs UVA 12569 - Planning mobile robot on Tree (EASY Version)

Problem P

Planning [m]obile robot on Tree (EASY Version)

We are given a connected, undirected graph G on n vertices. There is a mobile robot on one of the vertices; this vertex is labeled s. Each of several other vertices contains a single movable obstacle. The robot and the obstacles may only reside at vertices, although they may be moved across edges. No vertex may ever contain more than one movable entity (robot or obstacles).

In one step, we may move either the robot or one of the obstacles from its current position v to a vacant vertex adjacent to v. Our goal is to move the robot to a designated vertex t using the smallest number of steps possible.

Let us call this graph motion planning with one robot, or GMP1R for short. In this problem, we restrict the graph G to be a tree, namely TMP1R.

Here are some examples (gray circles represent obstacles).

Example 1 (s=1, t=3):

Move the obstacle 2-4, and then move the robot 1-2-3. Total: 3 moves.

Example 2 (s=1, t=4):

Move obstacle 2-5, then 3-2-6, and then move the robot 1-2-3-4. Total: 6 moves.

Example 3 (s=1, t=5):

Move the robot 1-6, then obstacle 2-1-7, then robot 6-1-2-8, then obstacle 3-2-1-6, then 4-3-2-1, and finally robot 8-2-3-4-5. Total: 16 moves.

Input

The first line contains the number of test cases T(T<=340). Each test case begins with four integers n, m, s, t(4<=n<=15, 0<=m<=n-2, 1<=s,t<=n, s!=t), the number of vertices, the number of obstacles and the label of the source and target. Vertices are numbered 1 to n. The next line contains m different integers not equal to s, the vertices containing obstacles. Each of the next n-1 lines contains two integers u and v (1<=u<v<=n), that means there is an edge u-v in the tree.

Output

For each test case, print the minimum number of moves k in the first line. Each of the next k lines contains two integers a and b, that means to move the robot/obstacle from a to b. If there is no solution, print -1. If there are multiple solutions, any will do. Print a blank line after each test case.

Sample Input

3
4 1 1 3
2
1 2
2 3
2 4
6 2 1 4
2 3
1 2
2 3
3 4
2 5
2 6
8 3 1 5
2 3 4
1 2
2 3
3 4
4 5
1 6
1 7
2 8

Output for the Sample Input

Case 1: 3
2 4
1 2
2 3

Case 2: 6
2 5
3 2
2 6
1 2
2 3
3 4

Case 3: 16
1 6
2 1
1 7
6 1
1 2
2 8
3 2
2 1
1 6
4 3
3 2
2 1
8 2
2 3
3 4
4 5

Bonus

You may find the sample data and special judge program in the gift package useful.

Notes

TMP1R can be solved in O(n4) time. That's overkill for this problem, but if you're interested, please take a look at this:

Vincenzo Auletta , Domenico Parente , Pino Persiano, A New Approach to Optimal Planning of Robot Motion on a Tree with Obstacles, in Proc. of the 4-th European Symposium on Algorithms, 1996.

Rujia Liu's Present 6: Happy 30th Birthday to Myself

Special thanks: Yubin Wang, Yao Li


题意:给出一颗数,书上面有一个robot和若干个障碍物,每一次能将一个障碍物或者robot移动到相邻的节点。需要经过一些操作让robot从s到t,问最少步数,并输出方案。

思路:我们用二进制对状态进行编码,我们用低4位来表示robot的位置,其他15位用来表示一个节点是否是障碍物。然后进行bfs就行了。不过我写的有点搓。。。9秒多过的。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 15+5;

int n , m , s , t , ptr;
int g[maxn][maxn];
int a[maxn*1000] , b[maxn*1000];
int d[1<<maxn];
int pre[1<<maxn];

struct Node
{
	int u , v;
	Node *next;
}edge[maxn*2] , *first[maxn];

void init() 
{
	ptr = 0;
	memset(first,0,sizeof(first));
}

void add(int u,int v)
{
	edge[++ptr].v = v;
	edge[ptr].next = first[u];
	first[u] = &edge[ptr];
}

struct State
{
	vector<int> obs;
	int bit;
	int robot;
	bool vis[maxn];
}start;

void input()
{
	start.obs.clear();
	memset(start.vis,false,sizeof(start.vis));
	scanf("%d%d%d%d",&n,&m,&s,&t);
	start.robot = s;
	start.bit = s-1;
	start.vis[s] = true;
	for (int i = 0 ; i < m ; ++i) {
		int x; scanf("%d",&x);
		start.vis[x] = true;
		start.obs.push_back(x);
		start.bit += 1<<(3+x);
	}
	memset(g,0,sizeof(g));
	for (int i = 0 ; i < n-1 ; ++i) {
		int u , v;
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
		g[u][v] = g[v][u] = 1;
	}

}

void output(int s) 
{
	if (pre[s]==-1) return;
	output(pre[s]);
	int x = pre[s];
	int y = x^s;
	if (y < 16) {
		int a = pre[s]%16+1;
		int b = s%16+1;
		printf("%d %d\n",a,b);
	} else {
		y = (x>>4)^(s>>4);
		int a = (x>>4)&y , b = (s>>4)&y;
		for (int j = 0 ; j < n ; ++j) if (a&(1<<j))
		{
			printf("%d",j+1);
			break;
		}
		for (int j = 0 ; j < n ; ++j) if (b&(1<<j)) 
		{
			printf(" %d\n",j+1);
			return;
		}
	}
}

void solve()
{
	memset(d,-1,sizeof(d));
	queue<State> q;
	q.push(start);
	d[start.bit] = 0;
	memset(pre,-1,sizeof(pre));
	while (q.size()) {
		State tmp = q.front(); q.pop();
		int u = tmp.robot;
		if (tmp.robot==t) {
			printf("%d\n",d[tmp.bit]);
			output(tmp.bit);
			return;
		}
		for (Node *p=first[u] ; p ; p=p->next) {
			int v = p->v;
			if (tmp.vis[v]) continue;
			State now = tmp;
			now.vis[u] = false;
			now.vis[v] = true;
			now.robot = v;
			now.bit = now.bit>>4<<4;
			now.bit += v-1;
			if (d[now.bit]!=-1) continue;
			d[now.bit] = d[tmp.bit]+1;
			pre[now.bit] = tmp.bit;
			q.push(now);
		}
		for (int i = 0 ; i < tmp.obs.size() ; ++i) {
			u = tmp.obs[i];
			for (Node *p=first[u] ; p ; p=p->next) {
				int v = p->v;
				if (tmp.vis[v]) continue;
				State now = tmp;
				now.obs[i] = v;
				now.vis[u] = false , now.vis[v] = true;
				now.bit += (1<<(v+3))-(1<<(u+3));
				if (d[now.bit]!=-1) continue;
				d[now.bit] = d[tmp.bit]+1;
				pre[now.bit] = tmp.bit;
				q.push(now);
			}
		}

	}
	printf("-1\n");
}

int main()
{
	int T; cin>>T;
	int k = 0;
	while (T--) {
		init();
		++k;
		input();
		printf("Case %d: ",k);
		solve();
		printf("\n");
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值