您的位置:首页 > 其它

sicily 2011. Nine Digits(广搜,康托展开)

2015-05-30 12:10 288 查看


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中山大学新手赛

这道题应该是考查广搜+康托压缩(康托展开),广搜用于找最短路,康托压缩是一个特殊的哈希函数,这个哈希函数好就好在它仅仅是一个大小为36W的int数组,能够省下不小内存。其实康托压缩就是把一个排列变成数字,这个数字是全排列中的第几个元素,比如132是123的第二个排列,就输出2。通过这个数字还能逆推回原来的序列。详情见百度百科:康托展开
有了这两个关键方法,设计算法的时候不要按部就班地从当前状态找到123456789这种顺序思路想,因为这样的时间复杂度和查询的次数是成线性关系增加的,会超时。应该从123456789这个状态出发,去找到其他所有状态,这个状态数为9!(9的全排列,包含了这个游戏所有的情况),而且搜索的时候数字变成了逆时针旋转(反过来)。这样只需要搜索一次。最后就是打表过程了。

#include <bits/stdc++.h>
using namespace std;

int fact[10] = {0,1,2,6,24,120,720,5040,40320,362880};//阶乘表
int src[10];
int dst[10] = {1,2,3,4,5,6,7,8,9};
int vis[400000];
int ans[400000];
struct pack{
int num,k;
pack(){}
pack(int num,int k):num(num),k(k){}
};

int cantor(int num){
int tmp[10];
int code=0;
for(int i=0;i<9;i++){
tmp[8-i]=num%10;
num/=10;
}
for(int i = 0;i <= 8;++i)//*****康托展开公式:当前位数的逆序数*该位数的阶乘****(本题重点)
{
int cnt = 0;
for(int j = i + 1;j <= 8;j++)
if(tmp[i] > tmp[j])    ++cnt;
code += fact[8-i] * cnt;
}
return code;
}

void op_1(int a[],int &num){
int tmp[10];
tmp[0]=a[1];
tmp[1]=a[4];
tmp[2]=a[2];
tmp[3]=a[0];
tmp[4]=a[3];
tmp[5]=a[5];
tmp[6]=a[6];
tmp[7]=a[7];
tmp[8]=a[8];
int hash=0;
for(int i=8;i>=0;i--){
hash+=tmp[i]*pow(10,8-i);
}
num = hash;
}
void op_2(int a[],int &num){
int tmp[10];
tmp[0]=a[0];
tmp[1]=a[2];
tmp[2]=a[5];
tmp[3]=a[3];
tmp[4]=a[1];
tmp[5]=a[4];
tmp[6]=a[6];
tmp[7]=a[7];
tmp[8]=a[8];
int hash=0;
for(int i=8;i>=0;i--){
hash+=tmp[i]*pow(10,8-i);
}
num = hash;
}
void op_3(int a[],int &num){
int tmp[10];
tmp[0]=a[0];
tmp[1]=a[1];
tmp[2]=a[2];
tmp[3]=a[4];
tmp[4]=a[7];
tmp[5]=a[5];
tmp[6]=a[3];
tmp[7]=a[6];
tmp[8]=a[8];
int hash=0;
for(int i=8;i>=0;i--){
hash+=tmp[i]*pow(10,8-i);
}
num = hash;
}
void op_4(int a[],int &num){
int tmp[10];
tmp[0]=a[0];
tmp[1]=a[1];
tmp[2]=a[2];
tmp[3]=a[3];
tmp[4]=a[5];
tmp[5]=a[8];
tmp[6]=a[6];
tmp[7]=a[4];
tmp[8]=a[7];
int hash=0;
for(int i=8;i>=0;i--){
hash+=tmp[i]*pow(10,8-i);
}
num = hash;
}

void bfs(){
memset(vis,0,sizeof(vis));
queue<pack> box;
int hash=0;
for(int i=8;i>=0;i--){
hash+=dst[i]*pow(10,8-i);
}
box.push(pack(hash,0));
while(!box.empty()){
int tmp[10];
int sum=box.front().num;
int k=box.front().k;
//cout<<sum<<endl;
box.pop();
//判重
int hash=cantor(sum);
if(vis[hash])
continue;
vis[hash]=1;
ans[hash]=k;

int cur[10];
int sum_tmp;
for(int i=0;i<9;i++){
cur[8-i]=sum%10;
sum/=10;
}
op_1(cur,sum_tmp);
box.push(pack(sum_tmp,k+1));
op_2(cur,sum_tmp);
box.push(pack(sum_tmp,k+1));
op_3(cur,sum_tmp);
box.push(pack(sum_tmp,k+1));
op_4(cur,sum_tmp);
box.push(pack(sum_tmp,k+1));
}
}
int main(){
bfs();
while(~scanf("%d",&src[0])){
for(int i=1;i<9;i++)
scanf("%d",&src[i]);
int hash=0;
for(int i=8;i>=0;i--){
hash+=src[i]*pow(10,8-i);
}
printf("%d\n",ans[cantor(hash)]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: