您的位置:首页 > 其它

Sicily 2011 Nine Digits

2015-02-08 19:28 381 查看

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:

[align=center]1 2 3[/align]
[align=center]4 5 6[/align]
[align=center]7 8 9[/align]
 
       At each step, you can do the following operation to the tiles: Choose 2 by 2 tiles, rotate the tiles in clockwise order. For example:
       1 2 3             4 1 3                           1 2 3             1 2 3
       4 5 6      =>   5 2 6             or           4 5 6      =>   4 8 5
       7 8 9             7 8 9                           7 8 9             7 9 6
 
       Write a program to find the minimum number of steps.

Input

 Input contains multiple test cases.

       Each test case is a description of a configuration of the nine tiles. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and from left to right within a row, where the tiles are
represented by numbers 1 to 9. For example:
       9 8 7
       6 5 4
       3 2 1
is described by this list:
       9 8 7 6 5 4 3 2 1

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息