sicily 2011. Nine Digits(广搜,康托展开)
来源:互联网 发布:下载zoom软件 编辑:程序博客网 时间:2024/06/09 22:33
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:
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 94 1 3 5 2 6 7 8 9
Sample Output
03
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)]); }}
- sicily 2011. Nine Digits(广搜,康托展开)
- Sicily 2011. Nine Digits
- Sicily 2011. Nine Digits
- 康托展开 双向广搜
- sicily 2011 Nine Digits
- Sicily 2011 Nine Digits
- HDU 1043 Eight(广搜+哈希+康托展开+打表)
- 2011. Nine Digits
- 借助八数码问题,双向广搜,康托展开,逆序数奇偶性
- HDU 1043 双向广搜 八数码 康托展开 逆序数
- POJ1077 HDU1043 Eight 八数码第四境界 双向广搜 康托展开 逆康托
- [Sicily 1150 1151 1515 魔板] BFS+判重(康托展开)
- csuoj1828Dictionary (康托展开)
- 排列(康托展开)
- 康托展开/逆康托展开
- 康托展开 & 康托逆展开
- 康托展开&逆康托展开
- 康托展开 康托逆展开
- oc函数
- 使用矩阵设置ImageView
- iOS开发UI基础—04UIButton练习之图片浏览器
- weblogic
- 新闻系统——真假分页
- sicily 2011. Nine Digits(广搜,康托展开)
- 懒惰、急躁和傲慢(Laziness, Impatience and hubris)
- mysql 执行计划解读
- 学习ASP.NET MVC5框架揭秘笔记-ASP.NET MVC路由(一)
- JQuery里面金额的格式化
- 封装JAVA数据库操作-学习
- PHP沉思录(转载)
- 如何看懂时序图(以1602为例)
- 《操作系统》操作系统中锁的实现原理