Sicily 2011 Nine Digits

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:

1 2 3
4 5 6
7 8 9
 
       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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章