题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567
解题思路:
根据X的位置将初始状态分为9种:first[9][10]=
{"X12345678", "1X2345678", ......, "12345678X"}。对于每一种初始状态,根据X的位置找到对应的 first[][]。比如说,对于146X25378到2478356X1的转换,146X25378对应的就是123X45678,那么此时2代表的其实就是4,3代表的就是6,4代表的是2,6代表的是3,那么2478356X1对应的就是4278653X1,我们只要求123X45678到4278653X1的转换就可以了。
这样一来这道题其实就跟HDU1042差不多了。我们还是用state这个结构体来表示每一种状态,用康托展开来为每一种状态找到一个对应的数。先以九个first[]为起点做9次BFS,记录下从每个firtst[]能到达的各个状态,然后正式询问的时候直接利用预处理好的信息来返回答案就好了。
具体的几个细节看代码注释吧。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <map> 4 using namespace std; 5 const int maxn = 5e5; 6 int cx[4] = { 1,0,0,-1 }, cy[4] = { 0,-1,1,0 }; 7 char go[6] = "dlru"; 8 9 struct state { 10 int from; //记录上一个状态,方便后期方向读取and 11 int pos; //记录X的位置 12 char num[10]; 13 char dos; //记录从上一步走到这一步要进行的操作 14 }; 15 state node[9][maxn]; 16 int vis[9][maxn]; //记录对应的状态在node[][]数组中的位置 17 char first[9][10] = { "X12345678","1X2345678","12X345678","123X45678","1234X5678","12345X678","123456X78","1234567X8","12345678X" }; 18 map<char, char> lists; //记录在此次询问中,1~8各个数字对应的数字 19 //康托展开 20 int factor[] = { 1,1,2,6,24,120,720,5040,40320,362880 }; 21 int cantor(char x[]) { 22 int sum = 0, s; 23 for (int i = 0; i<9; i++) { 24 s = 0; 25 for (int j = i + 1; j<9; j++) { 26 if (x[j]<x[i]) s++; 27 } 28 sum += s*factor[9 - i - 1]; 29 } 30 return sum; 31 } 32 void init(char now[10], int ind) { 33 node[ind][0].from = -1, node[ind][0].pos = ind; 34 for (int i = 0; i<9; i++) node[ind][0].num[i] = now[i]; 35 node[ind][0].num[9] = ‘\0‘; 36 vis[ind][cantor(now)] = -1; 37 int head = 0, ending = 1; 38 state nows, next; 39 while (head<ending) { //用数组写队列 40 nows = node[ind][head]; 41 for (int i = 0; i<4; i++) { 42 int x = nows.pos / 3, y = nows.pos % 3; 43 int dx = x + cx[i], dy = y + cy[i]; 44 if (dx<0 || dx>2 || dy<0 || dy>2) continue; 45 next.pos = dx * 3 + dy; 46 for (int j = 0; j<9; j++) 47 next.num[j] = nows.num[j]; 48 next.num[next.pos] = ‘X‘; 49 next.num[nows.pos] = nows.num[next.pos]; 50 int ct = cantor(next.num); 51 if (!vis[ind][ct]) { 52 vis[ind][ct] = ending; 53 next.dos = go[i]; 54 next.from = head; 55 node[ind][ending] = next; 56 ending++; 57 } 58 } 59 head++; 60 } 61 } 62 char ans[100]; //记录答案 63 int find_ans(int ind, int n) { 64 int ii = 0; 65 for (; node[ind][n].from != -1; n = node[ind][n].from) { 66 ans[ii++] = node[ind][n].dos; 67 } 68 return ii; 69 } 70 int main() { 71 int T; 72 char s[10], t[10]; 73 for (int i = 0; i<9; i++) 74 init(first[i], i); 75 scanf("%d", &T); 76 for (int i = 1; i <= T; i++) { 77 scanf("%s", s); 78 scanf("%s", t); 79 bool same = true; 80 for (int j = 0; j<9; j++) { 81 if (s[j] != t[j]) { 82 same = false; 83 break; 84 } 85 } 86 if (same) { //注意:s 和 t 一开始就相同的情况! 87 printf("Case %d: 0\n\n", i); 88 continue; 89 } 90 int ind = 0; 91 for (; ind<9; ind++) { 92 if (s[ind] == ‘X‘) break; 93 } 94 for (int j = 0; j<9; j++) { 95 if (j != ind) { 96 lists[s[j]] = first[ind][j]; 97 } 98 } 99 for (int j = 0; j<9; j++) { 100 if (t[j] != ‘X‘) { 101 t[j] = lists[t[j]]; 102 } 103 } 104 int ct = cantor(t); 105 int ll = find_ans(ind, vis[ind][ct]); 106 printf("Case %d: %d\n", i, ll); 107 for (int j = ll - 1; j >= 0; j--) { 108 printf("%c", ans[j]); 109 } 110 printf("\n"); 111 } 112 return 0; 113 }
时间: 2024-09-30 14:11:47