#include <cstdio> //
#include <cstring> //
#include <string> //
#include <set> //
#include <queue> //
#include <algorithm> //
#include <map> //
#include <stack> //
using namespace std; //
struct Node { //
int status; //
int pos; //
Node(int s = 0, int p = 0) { //
status = s; //
pos = p; //
} //
}; //初始化;
const int MAXN = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 + 10; //328890
int jie[10] = {1, 1 ,2 ,6 ,24 ,120 ,720, 5040, 40320 ,362880}; //
int dirx[] = {-1, 1, 0, 0}; //
int diry[] = {0, 0, -1, 1}; //
int father[2][MAXN]; //存储二个队列的已经存过的值
bool vis[2][MAXN]; //标记
queue<Node> q[2]; //
bool InRange(int x, int y) { //判断超出边界
return x >= 0 && x < 3 && y >= 0 && y < 3; //
} //
//
int Hash(string s) { //
int ans = 0; //
for (int i = 0; i < 9; ++i) { //
int rev = 0; //
for (int j = i + 1; j < 9; ++j) { //康托展开
if (s[i] > s[j]) ++rev; //
} //
ans += rev * jie[8 - i]; //
} //
return ans; //
}
string RevHash(int val) { //逆康托
string ans = ""; //
bool tag[10] = {}; //
for (int i = 0; i < 9; ++i) { //
int tNum = val / jie[8 - i] + 1; //
for (int j = 1; j <= tNum; ++j) { //
if (tag[j]) ++tNum; //
} //
val %= jie[8 - i]; //
ans += tNum + '0'; //
tag[tNum] = true; //
} //
return ans; //
} //
void PutPath(int mid) { //
stack<char> path; //
int a = mid; // a是康托值
while (father[0][a] != a)
{ //如果现在的a不是目的a继续;
string s = RevHash(a);//目标转码
string fs = RevHash(father[0][a]);//上一个康拓殖的转码
int pos, fpos; //
for (int i = 0; i < s.size(); ++i) {//
if (s[i] == '9') pos = i;//
if (fs[i] == '9') fpos = i;//
} //
if (pos / 3 == fpos / 3) //x 同x
{
if (pos % 3 < fpos % 3)
{
path.push('l');
}
else
{
path.push('r');
}
}
else
{
if (pos / 3 < fpos / 3)
{
path.push('u');
}
else
{
path.push('d');
}
}
a = father[0][a];
}
while (!path.empty()) { //
putchar(path.top()); //输出
path.pop();//
} //
int b = mid; //
while (father[1][b] != b) { //
string s = RevHash(b); //
string ss = RevHash(father[1][b]);//
int pos, spos; //
for (int i = 0; i < s.size(); ++i) { //
if (s[i] == '9') pos = i; //
if (ss[i] == '9') spos = i; //
} //
if (pos / 3 == spos / 3) { //
if (pos % 3 < spos % 3) { //
putchar('r'); //
} else { //
putchar('l');//
} //
} else { //
if (pos / 3 < spos / 3) { //
putchar('d'); //
} else { //
putchar('u');//
} //
} //
b = father[1][b];//
} //
putchar('\n'); //
} //
bool Expand(int id) { //
Node h = q[id].front(); q[id].pop(); //
int x = h.pos / 3, y = h.pos % 3; //
for (int i = 0; i < 4; ++i) { //
int nx = x + dirx[i]; //
int ny = y + diry[i]; //
int npos = nx * 3 + ny; //
if (!InRange(nx, ny)) continue; //
string ns = RevHash(h.status); //串
swap(ns[h.pos], ns[npos]); //交换
int hashVal = Hash(ns); //数值
if (!vis[id][hashVal]) { //没有的话
father[id][hashVal] = h.status;//上一个 ,fate存的是上一个上一个,,,
q[id].push(Node(hashVal, npos));//下一个
vis[id][hashVal] = true; //标记
if (vis[1 - id][hashVal]) { //如果有的话;
PutPath(hashVal); //找路径
return true; //结束
}
}
}
return false; // 继续
}
bool DBFS(int st, int ed, int pos) { //
memset(vis, 0, sizeof vis); //
memset(father, 0, sizeof father); ///
for (int i = 0; i < 2; ++i) //
while (!q[i].empty()) q[i].pop(); //初始化
father[0][st] = st; //
father[1][ed] = ed; //
vis[0][st] = true; //
vis[1][ed] = true; //
q[0].push(Node(st, pos)); //
q[1].push(Node(ed, 8)); //
while (!q[0].empty() && !q[1].empty())//
{ //
if (q[0].size() <= q[1].size())//
{ //
if (Expand(0)) return true; //
} //
else//
{ //
if (Expand(1)) return true;//
} //
} //
for (int i = 0; i < 2; ++i) //
while (!q[i].empty()) //
if (Expand(i)) //
return true; //
return false; //
}
int main() { //
char s[100];
while (gets(s) != NULL) {
int len = strlen(s), pos = 0; //
string ma = ""; //
for (int i = 0; i < len; ++i) { //
if (s[i] == 'x') { //
pos = ma.size(); //
s[i] = '9'; // 转化成123456789
} //
if (s[i] != ' ') { //
ma += s[i]; //
} //
} //
int rev = 0;
for (int i = 0; i < 9; ++i) { //
if (ma[i] == '9') continue; //
for (int j = i + 1; j < 9; ++j) { //逆序判断
if (ma[i] > ma[j]) ++rev; //
} //
} //
if (rev & 1) puts("unsolvable"); //
else DBFS(Hash(ma), 0, pos); //传输的都是康托值 0为123456789,ma为输入的那个; pos 为x的位置
} //
return 0; //
} //
八数码 康托 逆康托 哈希 双解码 双向广搜
最新推荐文章于 2023-08-26 20:53:44 发布