Time Limit: 2 secs, Memory Limit: 256 MB
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 contains multiple test cases.
Output the minimum number of steps on a single line for each test case.
1 2 3 4 5 6 7 8 9 4 1 3 5 2 6 7 8 9
0 3
每周一赛: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)]); } }
sicily 2011. Nine Digits(广搜,康托展开)
原文地址:http://blog.csdn.net/yuhao199555/article/details/46273459