Constraints
Time Limit: 2 secs, Memory Limit: 256 MB
Description
Nine tiles, each with a number from 1 to 9 on it, are packed into a 3 by 3 frame. Your task is to arrange the tiles so that they are ordered as:
Write a program to find the minimum number of steps.
Input
Input contains multiple test cases.
Output
Output the minimum number of steps on a single line for each test case.
Sample Input
1 2 3 4 5 6 7 8 9 4 1 3 5 2 6 7 8 9
Sample Output
0 3
Problem Source
每週一賽:2010中山大學新手賽
Solution:
這是一道隱式圖搜索,每一個狀態就是一個節點,最短路用寬度優先搜索就ok啦~
另外就是狀態編碼使用康託展開,節省空間和運算量,但是其實用map來實現字符串編碼也是ok的
注意的一點就是,這道題目的話可以用逆向思維做纔不會超時,因爲終點都是一樣的,那麼只需要從終點出發,逆向遍歷所有節點一遍,並且保存最短路徑的長度即可。
逆向遍歷的時候操作要從順時針變成逆時針~
#include <iostream>
#include <queue>
#include <cstring>
#define AIM 123456789
using namespace std;
int t[3][3], p[] = {0, 1, 3, 4}, ans[370000];
int fator[] = {0, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int operate(int x, int op)
{
int i, j, temp, ans = 0;
for (i = 2; i >= 0; -- i)
for (j = 2; j >= 0; -- j)
{
t[i][j] = x % 10;
x /= 10;
}
i = op / 3;
j = op % 3;
temp = t[i][j];
t[i][j] = t[i][j+1];
t[i][j+1] = t[i+1][j+1];
t[i+1][j+1] = t[i+1][j];
t[i+1][j] = temp;
for (i = 0; i < 3; ++ i)
for (j = 0; j < 3; ++ j)
{
ans *= 10;
ans += t[i][j];
}
return ans;
}
int encode(int x)//康託展開
{
int i, t[10], code;
i = code = 0;
while (x)
{
t[++i] = x % 10;
x /= 10;
}
for (i = 9; i >= 1; --i)
{
int temp = 0;
for (int j = i-1; j >= 1; --j) if (t[i] > t[j]) ++temp;
code += fator[i-1] * temp;
}
return code;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i, j;
memset(ans, -1, sizeof(ans));
queue<int> q;
q.push(123456789);
ans[0] = 0;
while (!q.empty())//BFS
{
int temp = q.front();
q.pop();
int t_c = encode(temp);
for (i = 0; i < 4; ++ i)
{
int next = operate(temp, p[i]);
int n_c = encode(next);
if (ans[n_c] == -1)
{
ans[n_c] = ans[t_c] + 1;
q.push(next);
}
}
}
while (cin >> t[0][0])
{
int initial = t[0][0];
for (i = 0; i < 3; ++ i)
for (j = 0; j < 3; ++ j)
{
if (i == 0 && j == 0) continue;
cin >> t[i][j];
initial *= 10;
initial += t[i][j];
}
cout << ans[encode(initial)] << '\n';
}
return 0;
}