UVA Planning mobile robot on Tree树上的机器人(状态压缩+bfs)

用(x,s)表示一个状态,x表示机器人的位置,s表示其他位置有没有物体。用个fa数组和act数组记录和打印路径,转移的时候判断一下是不是机器人在动。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 16;
const int maxe = 32;
const int MAXSTA = 491520+10; // 2^15*15
int head[maxn],to[maxe],nxt[maxe];
int ecnt;

void addEdge(int u,int v)
{
    to[ecnt] = v;
    nxt[ecnt] = head[u];
    head[u] = ecnt++;
}

struct Node
{
    int x,s;
    Node(){}
    Node(int X ,int S ){
        x = X; s = S;
    }
}q[MAXSTA];
int fa[MAXSTA],dist[MAXSTA];
struct Act
{
    int u,v;
    Act(int U = 0,int V = 0):u(U),v(V){}
}act[MAXSTA];
bool vis[32768][15];


int n,m,s,t,sta;

void print_ans(int u)
{
    if(~fa[u])print_ans(fa[u]);
    else return;
    printf("%d %d\n",act[u].u+1,act[u].v+1);
}

void bfs()
{
    int _front = 0,rear = 0;
    q[rear].x = s; q[rear].s = sta;
    fa[rear] = -1; dist[rear++] = 0;
    memset(vis,0,sizeof(vis));
    vis[sta][s] = true;
    while(_front<rear){
        Node &u = q[_front];
        if(u.x == t) {
            printf("%d\n",dist[_front]);
            print_ans(_front);
            return ;
        }
        for(int who = 0; who < n; who++) if(u.s>>who&1){
            int newSta = u.s^(1<<who);
            for(int i = head[who]; ~i; i = nxt[i]) if((u.s>>to[i]&1)^1) {
                Node &v = q[rear];
                v.s = newSta|1<<to[i];
                v.x = who != u.x ? u.x : to[i];
                if(!vis[v.s][v.x]){
                    vis[v.s][v.x] = true;
                    fa[rear] = _front;
                    act[rear].u = who;act[rear].v = to[i];
                    dist[rear++] = dist[_front] + 1;
                }
            }

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

int main()
{
    //freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    for(int cas = 1; cas <= T; cas++){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        s--; t--;
        sta = 1<<s;
        for(int i = 0; i < m; i++) {
            int t;
            scanf("%d",&t);
            sta |= 1<<(t-1);
        }
        ecnt = 0; memset(head,-1,sizeof(head));
        for(int i = 1; i < n; i++){
            int u,v; scanf("%d%d",&u,&v);
            u--;v--;
            addEdge(u,v); addEdge(v,u);
        }
        printf("Case %d: ",cas);
        bfs();
    }
    return 0;
}

 

posted @ 2015-07-31 11:51  陈瑞宇  阅读(238)  评论(0编辑  收藏  举报