HDU_1430
一开始以为只是个简单的bfs,结果发现写完超时,也就是说虽然总状态不多,但case很多,为了应对这样的情况比较好的办法就是预处理出来,然后O(1)查询并递归打印操作。
如果想预处理出来的话,那么必须要么固定起点,要么固定终点,由于这个题目要字典序最小,固定起点更方便。接着就是要将每个case转化成同一个起点就可以了。
#include<stdio.h> #include<string.h> #define HASH 100007 #define MAXD 100010 int op[][8] = { {7, 6, 5, 4, 3, 2, 1, 0}, {3, 0, 1, 2, 5, 6, 7, 4}, {0, 6, 1, 3, 4, 2, 5, 7}, }; struct HashMap { int head[HASH], size, next[MAXD], st[MAXD]; void init() { memset(head, -1, sizeof(head)); size = 0; } int find(int _st) { int i, h = _st % HASH; for(i = head[h]; i != -1; i = next[i]) if(st[i] == _st) break; return i; } void push(int _st) { int h = _st %HASH; st[size] = _st; next[size] = head[h], head[h] = size ++; } }hm; char a[10], b[10]; int pre[MAXD], code[10], q[MAXD], list[MAXD]; void decode(int st) { int i; for(i = 7; i >= 0; i --) code[i] = st & 7, st >>= 3; } int encode(int *code) { int i, ans = 0; for(i = 0; i < 8; i ++) ans = ans << 3 | code[i]; return ans; } void print(int cur) { if(pre[cur] == -1) return; print(pre[cur]); printf("%c", list[cur] + 'A'); } void prepare() { int i, j, k, x, y, rear, t[10]; for(i = 0; i < 8; i ++) code[i] = i; x = encode(code); q[0] = x, pre[0] = -1, rear = 1; hm.init(), hm.push(x); for(i = 0; i < rear; i ++) { x = q[i]; decode(x); for(j = 0; j < 3; j ++) { for(k = 0; k < 8; k ++) t[k] = code[op[j][k]]; y = encode(t); if(hm.find(y) == -1) { hm.push(y); pre[rear] = i, list[rear] = j, q[rear ++] = y; } } } } void solve() { int i, x, trans[10]; for(i = 0; i < 8; i ++) trans[a[i] - '1'] = i; for(i = 0; i < 8; i ++) code[i] = trans[b[i] - '1']; x = encode(code); i = hm.find(x); print(i); printf("\n"); } int main() { prepare(); while(scanf("%s%s", a, b) == 2) solve(); return 0; }