第一道冲破一周来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;
}