1. 程式人生 > >HDU_1430 魔板 【BFS+康託展開+置換】

HDU_1430 魔板 【BFS+康託展開+置換】

一、題面

POJ1430

二、分析

該題與之前做的八數碼不同,它是一個2*4的棋盤,並且沒有空的區域。這樣考慮的情況是很少的,依然結合康託展開,這時康託展開最多也只乘7的階乘,完全可以BFS先預處理一遍。

這裡需要注意,在處理的時候,仔細讀題,他的二維變一維的順序是順時針一遍讀過來的。

預處理完後,這裡需要用一個小技巧,就是置換。

$$ \begin{pmatrix} 3 & 2 & 1 & 4 & 5 & 6 & 7 & 8\\1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ \end{pmatrix} $$

上面使用的例子是$32145678$,然後相當於把它移到了和$12345678$一個起跑線上,這樣做的好處就是我們預處理的答案能夠適用所有情況。

假設目標狀態是$87654321$,這樣把目標狀態置換成與上面對應的即可。

$$ \begin{pmatrix} 8 & 7 & 6 & 5 & 4 & 3 & 2 & 1\\8 & 7 & 6 & 5 & 4 & 1 & 2 & 3 \\ \end{pmatrix} $$

這樣就可以直接輸出結果了。

三、AC程式碼

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <fstream>
  4 #include <cstring>
  5 #include <queue>
  6 #include <algorithm>
  7 
  8 using namespace std;
  9 
 10 const int MAXN = 40321;
 11 const int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880
}; //factorial 12 bool visit[MAXN]; 13 struct Node 14 { 15 int m[8]; 16 int cat; 17 }; 18 char op[] = "ABC"; 19 string ans[MAXN]; 20 21 void A(Node &t) 22 { 23 std::reverse(t.m , t.m+8); 24 } 25 26 void B(Node &t) 27 { 28 int temp = t.m[3]; 29 for(int i = 3; i > 0; i--) 30 { 31 t.m[i] = t.m[i-1]; 32 } 33 t.m[0] = temp; 34 temp = t.m[4]; 35 for(int i = 4; i < 7; i++) 36 { 37 t.m[i] = t.m[i+1]; 38 } 39 t.m[7] = temp; 40 } 41 42 void C(Node &t) 43 { 44 int temp = t.m[1]; 45 t.m[1] = t.m[6]; 46 t.m[6] = t.m[5]; 47 t.m[5] = t.m[2]; 48 t.m[2] = temp; 49 } 50 51 int Cantor(int s[]) 52 { 53 int t, ans = 1; 54 for(int i = 0; i < 8; i++) 55 { 56 t = 0; 57 for(int j = i+1; j < 8; j++) 58 { 59 if(s[j] < s[i]) 60 t++; 61 } 62 ans += t*fac[7-i]; 63 } 64 return ans; 65 } 66 67 void bfs() 68 { 69 memset(visit, 0, sizeof(visit)); 70 Node t; 71 for(int i = 0; i < 8; i++) 72 t.m[i] = i+1; 73 t.cat = Cantor(t.m); 74 queue<Node> Q; 75 ans[t.cat] = ""; 76 visit[t.cat] = 1; 77 Q.push(t); 78 while(!Q.empty()) 79 { 80 Node p = Q.front(); 81 Q.pop(); 82 for(int i = 0; i < 3; i++) 83 { 84 t = p; 85 switch(i) 86 { 87 case 0: A(t);break; 88 case 1: B(t);break; 89 case 2: C(t);break; 90 } 91 t.cat = Cantor(t.m); 92 if( !visit[t.cat] ) 93 { 94 95 ans[t.cat] = ans[p.cat]+op[i]; 96 visit[t.cat] = 1; 97 Q.push(t); 98 } 99 } 100 } 101 102 } 103 104 int main() 105 { 106 //freopen("input.txt", "r", stdin); 107 //freopen("out.txt", "w", stdout); 108 char s[10]; 109 int a[10] = {0}, b[8] = {0}; 110 bfs(); 111 while(scanf("%s", s)!=EOF) 112 { 113 for(int i = 0; i < 8; i++) 114 { 115 a[s[i] - '0'] = i+1; 116 } 117 scanf("%s", s); 118 for(int i = 0; i < 8; i++) 119 { 120 b[i] = a[s[i] - '0']; 121 } 122 cout << ans[Cantor(b)] << endl; 123 } 124 return 0; 125 }
View Code