生活随笔
收集整理的這篇文章主要介紹了
【 HDU1043-经典BFS+康拓展开 八数码】 (待更)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
給定一個序列,由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]);elseprintf("unsolvable\n");}return 0;
}
還可以用A*好像
?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的【 HDU1043-经典BFS+康拓展开 八数码】 (待更)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。