UVa #12569 Planning mobile robot on Tree (EASY Version) (习题7-11)

86 篇文章 0 订阅

第一道冲破一周来TLE阴影的题。


树的状态可以分成两部分:1、把机器人当成障碍,看树上哪些位置有东西  2、机器人的位置

比较好的表示状态的方法是一个二维数组,第一维保存树的二进制表达,第二维保存机器人的位置(1-15)


需要非常小心的是数组的大小:状态数量最多为(1<<15)*15,如果开小是RE,开大几倍的话memset会非常非常慢以致TLE



Run Time: 3.225s

#define UVa  "7-11.12569.cpp"

#include<cstring>
#include<cstdio>
#include<vector>

using namespace std;

struct State {
    int robot, tree, d;
    int x, y;               //action taken to get to current state.
};

//Global Variables. Reset upon Each Case!
const int maxstate = (1<<15)*15+10;        //pay attention to the size! it matters! No Less and No More
int T, n, m, s, t, kase = 1, init_tree, vis[1<<15][15];
vector<int> G[20];
State st[maxstate];
int fa[maxstate];
/

void init() {
    scanf("%d%d%d%d", &n, &m, &s, &t);
    memset(vis, 0, sizeof(vis));
    memset(fa, 0, sizeof(fa));
    init_tree = 0;
    for(int i = 0; i < n; i ++) G[i].clear();

    //Indexes starts from 1 in question. Here we start from 0.
    s = s - 1;
    t = t - 1;

    int tmp;
    for(int i = 0; i < m; i ++) {
        scanf("%d", &tmp);         //reading obstacles.
        init_tree |= (1<<(tmp-1));
    }
    init_tree |= (1<<s);

    for(int i = 0; i < n-1; i ++) {
        int a, b;
        scanf("%d%d", &a, &b);
        G[a-1].push_back(b-1);
        G[b-1].push_back(a-1);
    }
}

void print_ans(int u) {
    if(fa[u]) print_ans(fa[u]);
    printf("%d %d\n", st[u].x+1, st[u].y+1);
}

int solve() {
    int front = 0, rear = 1;
    State& start = st[front];
    start.d = 0;
    start.robot = s;
    start.tree = init_tree;
    start.x = start.y = 0;
    fa[front] = -1;

    while(front < rear) {
        State& u = st[front];
        if(u.robot == t) {
            printf("%d\n", u.d);
            print_ans(front);
            return 1;
        }
        for(int i = 0; i < n; i ++) if(u.tree & (1<<i)){
            for(int j = 0; j < G[i].size(); j ++) {
                if(u.tree & (1<<G[i][j])) continue;     //position occupied.
                State& v = st[rear];
                v.robot = u.robot;
                v.tree = u.tree;
                v.d = u.d + 1;
                v.tree += (1<<G[i][j]) - (1<<i);
                if(i == u.robot) v.robot = G[i][j];
                if(vis[v.tree][v.robot]) continue;
                vis[v.tree][v.robot] = 1;
                fa[rear] = front;
                v.x = i;
                v.y = G[i][j];
                rear ++;
            }
        }
        front ++;
    }
    printf("-1\n");
    return 0;
}

int main() {
    scanf("%d", &T);
    while(T--){
        init();
        printf("Case %d: ", kase ++);
        solve();
        printf("\n");
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值