UVA1343 The Rotation Game
阿新 • • 發佈:2018-12-23
題目大意
如圖所示形狀的棋盤上分別有8個1、2、3,要往A~H方向旋轉棋盤,使中間8個方格數字相同。圖(a)進行A操作後變為圖(b),再進行C操作後變為圖(c),這正是一個目標狀態(因為中間8個方格數字相同)。要求旋轉次數最少。如果有多解,操作序列的字典序應儘量小。
題目解析
本題是一個典型的狀態空間搜尋問題。本題採用IDEA*演算法,詳見程式碼。
#include<cstdio> #include<algorithm> using namespace std; /* A 0 B 1 00 01 02 03 H 7 04 05 06 07 08 09 10 C 2 11 12 G 6 13 14 15 16 17 18 19 D 3 20 21 22 23 F 5 E 4 */ int line[8][7] = { {0, 2, 6, 11, 15, 20, 22}, //A {1, 3, 8, 12, 17, 21, 23}, // B {10, 9, 8, 7, 6, 5, 4}, //C {19, 18, 17, 16, 15, 14, 13}//D }; int rev[] = {5, 4, 7, 6, 1, 0, 3, 2}; const int center[] = {6, 7, 8, 12, 17, 16, 15, 11}; int a[25]; char ans[1100]; bool isFinal(){ for(int i = 1; i < 8; ++i) if(a[center[i]] != a[center[0]]) return false; return true; } inline void move(int i){ int temp = a[line[i][0]]; for(int j = 0; j < 6; ++j) a[line[i][j]] = a[line[i]][j + 1]; a[line[i][6]] = temp; } int diff(int target){ int cnt = 0; for(int i = 0; i < 8; ++i) if(a[center[i]] != target) ++cnt; return cnt; } inline int h(){ return min(min(diff(1), diff(2)), diff(3)); } bool dfs(int d, int maxd){ if(isFinal()){ ans[d] = '\0'; printf("%s\n", ans); return true; } if(h() + d > maxd) return false; for(int i = 0; i < 8; ++i){ ans[d] = 'A' + i; move(i); if(dfs(d + 1, maxd)) return true; move(rev[i]); } return false; } int main(){ for(int i = 4; i < 8; ++i) for(int j = 0; j < 7; ++j) line[i][j] = line[rev[i]][6 - j]; while(scanf("%d", &a[0]) == 1 && a[0]){ for(int i = 1; i < 24; ++i) scanf("%d", &a[i]); for(int i = 0; i < 24; ++i) if(!a[i]) return 0; if(isFinal()){ printf("No moves needed\n"); }else{ for(int maxd = 1; ; maxd++) if(dfs(0, maxd)) break; } printf("%d\n", a[6]); } return 0; }