【 HDU1043-經典BFS+康拓展開 八數碼】 (待更)
阿新 • • 發佈:2018-12-01
給定一個序列,由1~8數字和字母x組成,表示的是一個3*3的矩形。每次操作x都能與相鄰的數字交換,問如何操作才能使得序列為{1,2,3,4,5,6,7,8,x}。
//多組資料-需要計算全部路徑後直接輸出 //反向搜尋+打表(離線) #include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define MAX 400000 #define AIM 46234 //123456780對應的康託Hash值 bool v[MAX]; char path[MAX][40]; //總路徑 int len; //路徑長 /*udlr*/ char *dir = "durl"; //反向搜尋 int mov[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; //八數碼狀態結構體 struct Node{ int s[9]; int loc; //空位 int status; //Hash值-排列值 int fa; //記錄父狀態 char d; //到此狀態的移動方向 }n[MAX]; int fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 }; //康託逆展開-返回Hash值 int Inverse_cantor(int s[9]) { int sum = 0; for (int i = 0; i < 9; i++) { int num = 0; //逆序數計數器 for (int j = i + 1; j < 9; j++) if (s[j] < s[i]) num++; sum += num*fac[9 - i - 1]; } return sum + 1; } /*反向記錄路徑*/ void count_path(Node end) { int status = end.status; int f = end.fa; len = 0; path[status][len++] = end.d; while (f) { path[status][len++] = n[f].d;//方向記錄 f = n[f].fa; //查詢父結點 } } void BFS() { memset(v, 0, sizeof(v)); Node next; //下一臨時狀態 int head = 0, tail = 0; /*目標狀態*/ for (int i = 0; i < 8; i++) n[0].s[i] = i + 1; n[0].s[8] = 0; n[0].loc = 8; n[0].status = AIM; v[AIM] = true; while (head <= tail) //模擬佇列 { //計算二維座標 int x = n[head].loc / 3; int y = n[head].loc % 3; for (int i = 0; i < 4; i++) //遍歷四方向 { int tx = x + mov[i][0]; int ty = y + mov[i][1]; if (tx < 0 || tx>2 || ty < 0 || ty>2)continue; //新狀態更新 next = n[head]; next.loc = tx * 3 + ty; //計算新空位 next.s[n[head].loc] = next.s[next.loc]; //原空位替換 next.s[next.loc] = 0; //新空位 next.fa = head; next.d = dir[i]; next.status = Inverse_cantor(next.s); //判重併入隊 if (!v[next.status]) { v[next.status] = true; count_path(next); n[++tail] = next; } } head++; } } int main() { /* BFS-打表 */ BFS(); /*input*/ char ch[3]; Node cur; while (scanf("%s", ch) != EOF) { if (!strcmp(ch, "x")) cur.s[0] = 0, cur.loc = 0; else cur.s[0] = ch[0] - '0'; for (int i = 1; i < 9; i++) { scanf("%s", ch); if (!strcmp(ch, "x")) cur.s[i] = 0, cur.loc = i; else cur.s[i] = ch[0] - '0'; } cur.status = Inverse_cantor(cur.s); /*output*/ if (v[cur.status]) printf("%s\n", path[cur.status]); else printf("unsolvable\n"); } return 0; }
還可以用A*好像