// 此博文为迁移而来,写于2015年3月14日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vtyo.html

1、含义
       一个很简单的概念哈,其实它的本质就是将你当前状态压缩成一个数,且状态与数一一对应,故一般用在哈希判重,因为有时哈希判重会存不下,或者根本不可能。这是一项辅助的知识点,故不详解。
 
2、公式
       X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0,其中,a[i]为整数,并且0<=a[i]<=i<=n。a[i]的意义参见举例中的解释部分。
       举例
       例如,3 5 7 4 1 2 9 6 8 展开为 98884。因为X=2*8!+3*7!+4*6!+2*5!+0*4!+0*3!+2*2!+0*1!+0*0!=98884.
       排列的第一位是3,比3小的数有两个,以这样的数开始的排列有8!个,因此第一项为2*8! 排列的第二位是5,比5小的数有1、2、3、4,由于3已经出现,因此共有3个比5小的数,这样的排列有7!个,因此第二项为3*7!
以此类推,直至0*0!。
 
3、例题
       很好理解的东西我们就直接通过例题来看如何实现。
-------------------------------------------------------------------------------------------------------
数字矩阵(number)
 
问题描述
还别说ZZD平常毛毛躁躁的,考场上的他可毫不含糊,孤身闯阵,奋勇杀敌,多般神勇,一鼓作气地攻下了第一题,第二题,第三题,真可谓一夫当关,万夫莫开啊!当下正浩浩荡荡地朝第四题前进呢。但是,敌人也不是吃干饭的,经受了一二三题的失败后,他们摸清了一个事实,那就是ZZD率领的银河站队所摆的战阵------银河九宫阵(指横、竖和对角线上的战士战斗力之和都等于15的九宫格,每个格子中的数都在1~9之间,并且不重复)非常厉害,所以在第三题之后他们就对这种战阵进行了超强的光子干扰,也就是使阵中每个战士的战斗资料相互间打乱,这样就让战阵的战斗力大打折扣。难怪刚才刷第四题的时候特别困难,ZZD恍然大悟。而他只会领兵作战,至于修复资料的工作自然就叫给了变成天才的你来解决。所以你只需告诉ZZD资料最少移动的步数(指战斗值上下或左右相交换),如果怎么移动都无法恢复战阵,则输出-1。
 
输入文件(number.in)
一共有50个战阵给你修复;
每个战阵用一个3*3的数字矩阵表示,每一个数表示一个战士的战斗值;
相邻两个数字距阵不用空行隔开。
 
输出文件(number.out)
应该有50行,每行对应一个距阵修复的最少步数,如无法修复,则为-1。
 
输入样例:
1 5 2
6 9 3
8 4 7
1 8 6
4 2 3
9 5 7
5 1 9
4 8 3
2 7 6
 
输出样例
5
6
6
 
样例说明
样例就只给出3个供大家参考啦!
-----------------------------------------------------------------------------------------------------
题解:这道题是搜索题,但是不是直接暴搜就搜得到的。不难看出,这道题如果不在BFS的过程中用哈希判重,那么将会爆栈。但是,我们总不可能用九维数组来存hash吧?正如今天的主题一样,在哈希判重时,它需要用到康拓展开。康拓展开为什么能够在这里使用?因为对于栈内每一个矩阵,都有且仅有1-9这9个数字且不重复,所以康拓展开式和矩阵一一对应,可以很方便的判重了。
 
代码:
#include<cstdio>
#include<cstring>
#define MAXN 100005
 
const int JC[9]={0,1,2,6,24,120,720,5040,40320};
struct Queue
{
  int map[4][4],dep;
};
Queue q[MAXN]; 
int hash[3628810];
 
void Copy(int head,int tail)
{
  for (int i=1;i<=3;i++)
    for (int j=1;j<=3;j++)
      q[tail].map[i][j]=q[head].map[i][j];
}
 
void Swap(int x1,int y1,int x2,int y2,int tail)
{
  int temp;
  temp=q[tail].map[x1][y1];
  q[tail].map[x1][y1]=q[tail].map[x2][y2];
  q[tail].map[x2][y2]=temp;
}
 
int Cantor(int tail)
{
  int count[10],ans=0,now=8,tot=0,temp[10];
  memset(count,0,sizeof(count));
  for (int i=1;i<=3;i++)
    for (int j=1;j<=3;j++)
    {
      tot++;
      temp[tot]=q[tail].map[i][j];
    }
  for (int i=1;i<=8;i++)
  {
    for (int j=i+1;j<=9;j++)
      if (temp[i]>temp[j]) count[now]++;
    ans+=JC[now]*count[now];
    now--;
  }
  return ans;
}
 
int Check(int tail)
{
  if (q[tail].map[1][1]+q[tail].map[1][2]+q[tail].map[1][3]!=15) return 0;
  if (q[tail].map[2][1]+q[tail].map[2][2]+q[tail].map[2][3]!=15) return 0;
  if (q[tail].map[3][1]+q[tail].map[3][2]+q[tail].map[3][3]!=15) return 0;
  if (q[tail].map[1][1]+q[tail].map[2][1]+q[tail].map[3][1]!=15) return 0;
  if (q[tail].map[1][2]+q[tail].map[2][2]+q[tail].map[3][2]!=15) return 0;
  if (q[tail].map[1][3]+q[tail].map[2][3]+q[tail].map[3][3]!=15) return 0;
  if (q[tail].map[1][1]+q[tail].map[2][2]+q[tail].map[3][3]!=15) return 0;
  if (q[tail].map[3][1]+q[tail].map[2][2]+q[tail].map[1][3]!=15) return 0;
  return 1;
}
 
int BFS()
{
  int head=1,tail=2;
  while (head!=tail)
  {
    for (int i=1;i<=2;i++)
      for (int j=1;j<=3;j++)
      {
        Copy(head,tail);
        Swap(i,j,i+1,j,tail);
        int NowCantor=Cantor(tail);
        if (hash[NowCantor]!=1)
        {
          hash[NowCantor]=1;
          q[tail].dep=q[head].dep+1;
          if (Check(tail)==1) return q[tail].dep;
          tail++;
        }
      }
    for (int i=1;i<=3;i++)
      for (int j=1;j<=2;j++)
      {
        Copy(head,tail);
        Swap(i,j,i,j+1,tail);
        int NowCantor=Cantor(tail);
        if (hash[NowCantor]!=1)
        {
          hash[NowCantor]=1;
          q[tail].dep=q[head].dep+1;
          if (Check(tail)==1) return q[tail].dep;
          tail++;
        }
      }
    head++;
  }
  return -1;
 
int main()
{
  freopen("number.in","r",stdin);
  freopen("number.out","w",stdout);
  for (int t=1;t<=50;t++)
  {
    for (int i=1;i<=3;i++)
      for (int j=1;j<=3;j++)
        scanf("%d",&q[1].map[i][j]);
    printf("%d\n",BFS());
    memset(hash,0,sizeof(hash));
  }
  return 0;
}

[知识点]Cantor展开的更多相关文章

  1. CDOJ 485 UESTC 485 Game (八数码变形,映射,逆cantor展开)

    题意:八数码,但是转移的方式是转动,一共十二种,有多组询问,初态唯一,终态不唯一. 题解:初态唯一,那么可以预处理出012345678的所有转移情况,然后将初态对012345678做一个映射,再枚举一 ...

  2. poj 1077 Eight (八数码问题——A*+cantor展开+奇偶剪枝)

    题目来源: http://poj.org/problem?id=1077 题目大意: 给你一个由1到8和x组成的3*3矩阵,x每次可以上下左右四个方向交换.求一条路径,得到12345678x这样的矩阵 ...

  3. POJ 1077 Eight (BFS+康托展开)详解

    本题知识点和基本代码来自<算法竞赛 入门到进阶>(作者:罗勇军 郭卫斌) 如有问题欢迎巨巨们提出 题意:八数码问题是在一个3*3的棋盘上放置编号为1~8的方块,其中有一块为控制,与空格相邻 ...

  4. 魔板 (bfs+康托展开)

    # 10027. 「一本通 1.4 例 2」魔板 [题目描述] Rubik 先生在发明了风靡全球魔方之后,又发明了它的二维版本--魔板.这是一张有 888 个大小相同的格子的魔板: 1 2 3 4 8 ...

  5. MySQL面试必考知识点:揭秘亿级高并发数据库调优与最佳实践法则

    做业务,要懂基本的SQL语句: 做性能优化,要懂索引,懂引擎: 做分库分表,要懂主从,懂读写分离... 数据库的使用,是开发人员的基本功,对它掌握越清晰越深入,你能做的事情就越多. 今天我们用10分钟 ...

  6. [转]10分钟梳理MySQL知识点:揭秘亿级高并发数据库调优与最佳实践法则

    转:https://mp.weixin.qq.com/s/RYIiHAHHStIMftQT6lQSgA 做业务,要懂基本的SQL语句: 做性能优化,要懂索引,懂引擎: 做分库分表,要懂主从,懂读写分离 ...

  7. 10分钟梳理MySQL核心知识点

    数据库的使用,是开发人员的基本功,对它掌握越清晰越深入,你能做的事情就越多. 做业务,要懂基本的SQL语句:做性能优化,要懂索引,懂引擎:做分库分表,要懂主从,懂读写分离... 今天我们用10分钟,重 ...

  8. XHTML标签的嵌套规则分析

    在 XHTML 的语言里,我们都知道:ul 标签包含着 li.dl 标签包含着 dt 和 dd——这些固定标签的嵌套规则十分明确.但是,还有许多标签是独立的,它们没有被捆绑在一起,比如 h1.div. ...

  9. <HTML5和CSS3响应式WEB设计指南>译者序

    "不是我不明白,这世界变化快."崔健的这首歌使用在互联网领域最合适不过.只短短数年的功夫,互联网的浪潮还没过去,移动互联网的时代已经来临.人们已经习惯将越来越多的时间花在各种移动设 ...

随机推荐

  1. 基于SNMP的路由拓扑发现算法收集

    一.三层(网络层)发现 算法来源:王娟娟.基于SNMP的网络拓扑发现算法研究.武汉科技大学硕士学位论文,2008 数据结构: 待检路由设备网关链表:存放指定深度内待检路由设备的网关信息,处理后删除. ...

  2. Delphi中的变量作用域简介

    1.在函数或过程中声明的变量是局部变量,只能在函数或过程中使用 2.在单元的implementation部分声明的变量是单元级的(又称模块级.窗体级)变量,该单元的所有函数与过程都能使用,其他引用该单 ...

  3. 攻城狮在路上(贰) Spring(四)--- Spring BeanFactory简介

    BeanFactory时Spring框架最核心的接口,它提供了高级IoC的配置机制,使管理不同类型的Java对象成为了可能.我们一般称BeanFactory为IoC容器.BeanFactory是Spr ...

  4. mac下php开发环境搭建+CI框架使用

    一.启动apache: apachectl start 停止: apachectl stop 配置文件: vi /etc/apache2/httpd.conf 一.修改端口 因为80端口不想被占用,8 ...

  5. js注入

    1.JavaScript注入就是在浏览器地址栏中输入一段js代码,用来改变页面js变量.页面标签的内容. 使用Javascript注入,用户不需要关闭或保存网页就可以改变其内容,这是在浏览器的地址栏上 ...

  6. HDU 1561 The more, The Better 树形DP

    The more, The Better Problem Description   ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M ...

  7. hdu 3183(贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 思路:比较前后两个相邻的字符,如果前面一个字符大于后面一个字符,就把它去掉. #include ...

  8. java大数取模

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1214 用java写大数果然是方便多了! import java.math.BigInt ...

  9. Hadoop Mapreduce分区、分组、二次排序过程详解[转]

    原文地址:Hadoop Mapreduce分区.分组.二次排序过程详解[转]作者: 徐海蛟 教学用途 1.MapReduce中数据流动   (1)最简单的过程:  map - reduce   (2) ...

  10. bat 炸弹升级

    转自:http://digi.163.com/15/0320/06/AL4LP0QD0016192R.html 第1页:什么是批处理炸弹? 最近网上流传一个叫做<大哥别杀我>视频纷纷遭到网 ...