zoukankan      html  css  js  c++  java
  • [知识点]Cantor展开

    // 此博文为迁移而来,写于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 ",BFS());
        memset(hash,0,sizeof(hash));
      }
      return 0;
    }
  • 相关阅读:
    Two Sum II
    Subarray Sum
    Intersection of Two Arrays
    Reorder List
    Convert Sorted List to Binary Search Tree
    Remove Duplicates from Sorted List II
    Partition List
    Linked List Cycle II
    Sort List
    struts2结果跳转和参数获取
  • 原文地址:https://www.cnblogs.com/jinkun113/p/4677226.html
Copyright © 2011-2022 走看看