典型的IDA*题目
估值函数:从当前状态移动到目标状态所需的最小步数(我们可以通过曼哈顿距离进行估值),用于剪枝
迭代:此处我们不再使深度每次加1,而是在搜索过程当中,记录大于len(len表示此次搜索的限制深度)的所有值中的最小值,作为下次迭代的限制深度
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <stack>
using namespace std;
int factor[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int dx[] = {1, 0, 0, -1};
int dy[] = {0, -1, 1, 0};
int target, posx, posy, len, nextlen;
bool vis[363000];
int a[3][3], b[3][3], px[9], py[9];
stack<int> s;
int cantor(int t[][3])
{
int x[9];
for (int i = 0; i < 9; i++)
x[i] = t[i / 3][i % 3];
int ans = 0;
for (int i = 0; i < 9; i++)
{
int cnt = 0;
for (int j = i + 1; j < 9; j++)
if (x[i] > x[j])
cnt++;
ans += cnt * factor[9 - i - 1];
}
return ans;
}
int geth(int t[][3])
{
int ans = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
if (!t[i][j]) continue;
ans += abs(i - px[t[i][j]]) + abs(j - py[t[i][j]] % 3);
}
return ans;
}
bool ID_Astar(int state, int x, int y, int step)
{
if (state == target)
return true;
for (int i = 0; i <= 3; i++)
{
int cx = x + dx[i];
int cy = y + dy[i];
if (0 <= cx && cx <= 2 && 0 <= cy && cy <= 2)
{
swap(a[x][y], a[cx][cy]);
int f = step + 1 + geth(a);
if (f > len)
nextlen = min(f, nextlen);
if (f <= len)
{
int nextstate = cantor(a);
if (!vis[nextstate])
{
vis[nextstate] = true;
s.push(i);
if (ID_Astar(nextstate, cx, cy, step + 1))
return true;
s.pop();
vis[nextstate] = false;
}
}
swap(a[x][y], a[cx][cy]);
}
}
return false;
}
int main()
{
int T, k = 0;
cin >> T;
while (T--)
{
char ch;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
cin >> ch;
if (ch == 'X')
a[i][j] = 0, posx = i, posy = j;
else
a[i][j] = ch - '0';
}
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
cin >> ch;
if (ch == 'X')
b[i][j] = 0;
else
{
b[i][j] = ch - '0';
px[b[i][j]] = i;
py[b[i][j]] = j;
}
}
target = cantor(b);
int start = cantor(a);
cout << "Case " << ++k << ": ";
memset(vis, 0, sizeof(vis));
vis[start] = true;
len = 0;
for (;;)
{
nextlen = 0x3f3f3f3f;
while (!s.empty()) s.pop();
if (ID_Astar(start, posx, posy, 0)) break;
if (nextlen == 0x3f3f3f3f)
nextlen = len + 1;
len = nextlen;
}
char cc[] = {'d', 'l', 'r', 'u'};
vector<int> ans;
while (!s.empty())
ans.push_back(s.top()), s.pop();
cout << ans.size() << endl;
for (int i = ans.size() - 1; i >= 0; i--)
cout << cc[ans[i]];
cout << endl;
}
return 0;
}