bfs + 字符串哈希
D - 8 Puzzle on Graph (atcoder.jp)
O(9!)
#### C++ 代码
//八数码变形
#include<bits/stdc++.h>
using namespace std;
const int N = 80; //最多36条边,无向边开双倍空间
int a[N];
int h[N], e[N], ne[N], idx;
string start;
map<string, int> mp;
queue<string> q;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int bfs(string start)
{
mp[start] = 0;
q.push(start);
while(q.size())
{
string t = q.front();
if(t == "123456789") return 0; //如果已经找到最终结果,则直接结束
q.pop();
int u;
for(int i=0; i<t.size(); i++)
if(t[i] == '9')
u = i+1;
for(int i=h[u]; ~i; i=ne[i])
{
int j = e[i];
string tt = t;
swap(tt[u-1], tt[j-1]);
if(!mp.count(tt)) //count()函数,判断该状态是否出现过
{
mp[tt] = mp[t]+1;
q.push(tt);
}
}
}
return 0;
}
int main()
{
memset(h, -1, sizeof h);
int m; cin >> m;
while(m--)
{
int a, b; cin >> a >> b;
add(a, b);
add(b, a);
}
for(int i=1; i<=8; i++)
{
int x; cin >> x;
a[x] = i;
}
for(int i=1; i<=9; i++)
{
if(!a[i])
{
a[i] = 9; break;
}
}
for(int i=1; i<=9; i++)
start += a[i]+'0';
bfs(start); //将编号为1-9的9个点上的块的编号序列作为状态,空的结点上的编号记为9
if(!mp.count("123456789")) puts("-1");
else cout << mp["123456789"] << endl;
return 0;
}