您的位置:首页 > 其它

UVA--12569(状态压缩+bfs)

2015-05-05 17:26 351 查看

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
***,卡了这么久就是因为初始化的时候不小心把N多减了个1,代码写的很不精简,其实robot和普通的障碍物不用分开处理的,稍微判断下就好了,题意:给出一颗树,树上面有一个robot和若干个障碍物,每一次能将一个障碍物或者robot移动到相邻的节点。需要经过一些操作让robot从s到t,问最少步数,并输出方案。vis第一位表示机器人所在位置,后一维用状态压缩表示各个障碍物的位置。改的要死要死的。
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<string>#include<cmath>#include<queue>#include<vector>#include<map>#include<set>#define INF 0x3f3f3f3f#define mem(a,b) memset(a,b,sizeof(a))using namespace std;const int maxd=200000+5;const int maxn=10000+5;#define lson l,m,rt<<1#define rson m+1,r,rt<<1 | 1typedef long long ll;typedef pair<int,int> pii;//---------------------------int vis[20][1<<16];int n,m,s,t,tmp;vector<int> g[20];typedef struct info{    int pos,state,step;};typedef struct info2{    int pos,state,step;    int x,y;};info2 pre[20][1<<16];void init(){    scanf("%d%d%d%d",&n,&m,&s,&t);    tmp=0;    mem(vis,0);    for(int i=0; i<n; ++i)        g[i].clear();    for(int i=0;i<m;++i)    {        int x;        scanf("%d",&x);        tmp|=(1<<(x-1));    }    --s,--t;    tmp|=(1<<s);    vis[s][tmp]=1;    for(int i=0;i<n-1;++i)    {        int u,v;        scanf("%d%d",&u,&v);        g[u-1].push_back(v-1);        g[v-1].push_back(u-1);    }}void print(int pos,int sta){    vector<info2> v;    info2 tmp=pre[pos][sta];    while(tmp.step)    {        v.push_back(tmp);        tmp=pre[tmp.pos][tmp.state];    }    v.push_back(tmp);    for(int i=v.size()-1; i>=0; --i)    {        printf("%d %d\n",v[i].x+1,v[i].y+1);    }    printf("\n");}void bfs(){    queue<info> q;    q.push( {s,tmp,0} );    while(!q.empty())    {        info now=q.front();        q.pop();        int tpos=now.pos;        int tstate=now.state;        int tstep=now.step;        if(tpos==t)        {            printf("%d\n",tstep);            print(tpos,tstate);            return;        }        for(int i=0; i<n; ++i)            if( ( (1<<i) & tstate) ==(1<<i) ) ///此处有物体可以移动                for(int j=0; j<g[i].size(); ++j)                {                    if( ((1<<g[i][j]) & tstate) ==(1<<g[i][j]) ) continue;///此位置被占                    int temp=( tstate & (~(1<<i))) | (1<<g[i][j] );                    if(i==tpos)///如果移动的是机器人                    {                        if(vis[ g[i][j] ][temp]) continue;///此状态出现过                        q.push( { g[i][j] ,temp,tstep+1} );                        vis[ g[i][j] ][ temp ]=1;                        pre[ g[i][j] ][ temp ]= {tpos,tstate,tstep,i,g[i][j]};                    }                    else                    {                        if(vis[tpos][temp]) continue;///此状态出现过                        q.push( {tpos,temp,tstep+1} );                        vis[ tpos ][ temp ]=1;                        pre[ tpos ][ temp ]= {tpos,tstate,tstep,i,g[i][j]};                    }                }    }    printf("-1\n\n");    return;}int main(){    int kase;    freopen("1.txt","r",stdin);    scanf("%d",&kase);    for(int i=1; i<=kase; ++i)    {        printf("Case %d: ",i);        init();        bfs();    }    return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: