zoukankan      html  css  js  c++  java
  • Eight 全排列的哈希函数

    Problem Description
    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as: 

    1 2 3 4
    5 6 7 8
    9 10 11 12
    13 14 15 x

    where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle: 

    1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
    5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
    9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
    13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
    r-> d-> r->

    The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively. 

    Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and 
    frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

    In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three 
    arrangement.
     
    Input
    You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle 

    1 2 3 
    x 4 6 
    7 5 8 

    is described by this list: 

    1 2 3 x 4 6 7 5 8
     
    Output
    You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
     
    Sample Input
    2 3 4 1 5 x 7 6 8
     
    Sample Output
    ullddrurdllurdruldr
    ***************************************************************************************************************************
    全排列的哈希函数
    K = a1*1! + a2*2! + a3*3! + ... + an*n! (其中0 <= ai <= i),
    ***************************************************************************************************************************
      1 /*
      2 全排列的哈希函数
      3 */
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<queue>
      7 #include<iostream>
      8 using namespace std;
      9 
     10 const int maxn = 362881;//根据全排列的哈希函数,n+1个数的排列可以对应n个数的多进制形式,这里九个数对应多进制的最大值为9!-1;
     11 int factorial[9] = {1,1,2,6,24,120,720,5040,40320};
     12 int pow[9] = {100000000,10000000,1000000,100000,10000,1000,100,10,1};
     13 int head,tail;
     14 bool vis[maxn];
     15 
     16 struct node
     17 {
     18     char status;
     19     int id,num,pre;
     20 }que[maxn];
     21 
     22 int hash(int num)//全排列的哈希函数
     23 {
     24     int a[10],key,i,j,c;
     25     for(i = 0; i < 9; i++)
     26     {
     27         a[i] = num%10;//a数组倒着存的num,所以求逆序数的时候条件是a[j]<a[i];
     28         num = num/10;
     29     }
     30     key = 0;
     31     for(i = 1; i < 9; i++)
     32     {
     33         for(j = 0,c = 0; j < i; j++)
     34         {
     35             if(a[j] < a[i])
     36                 c++;
     37         }
     38         key += c*factorial[i];
     39     }
     40     return key;
     41 }
     42 
     43 void change(int num,int a,int b,char status)//a位置上的数和b位置上的数互换;
     44 {
     45     int n1,n2;
     46     n1 = num/pow[a]%10;
     47     n2 = num/pow[b]%10;
     48     num = num - (n1-n2)*pow[a] + (n1-n2)*pow[b];
     49     int key = hash(num);
     50     if(!vis[key])
     51     {
     52         vis[key] = true;
     53         que[tail].num = num;
     54         que[tail].id = b;
     55         que[tail].status = status;
     56         que[tail++].pre = head;
     57     }
     58 }
     59 
     60 //打印路径
     61 void print(int head)
     62 {
     63     char s[100];
     64     int c = 0;
     65     while(que[head].status != 'k')
     66     {
     67         s[c++] = que[head].status;
     68         head = que[head].pre;
     69     }
     70     s[c] = '';
     71     for(int i = c-1; i >= 0; i--)
     72     {
     73         printf("%c",s[i]);
     74     }
     75     printf("
    ");
     76 }
     77 
     78 int main()
     79 {
     80     char c;
     81     int num,id,t;
     82 
     83     num = 0;
     84     for(int i = 0; i < 9; i++)
     85     {
     86         cin>>c;
     87         if(c == 'x')
     88         {
     89             t = 9;
     90             id = i;
     91         }
     92         else t = c-'0';
     93         num = 10*num+t;
     94     }
     95     bool flag = false;
     96     memset(vis,false,sizeof(vis));
     97 
     98     head = 0;
     99     tail = 1;
    100     que[0].id = id;
    101     que[0].num = num;
    102     que[0].status = 'k';
    103 
    104     while(head < tail)
    105     {
    106         num = que[head].num;
    107         id = que[head].id;
    108         if(num == 123456789)
    109         {
    110             flag = true;
    111             break;
    112         }
    113         if(id > 2)
    114             change(num,id,id-3,'u');
    115 
    116         if(id < 6)
    117             change(num,id,id+3,'d');
    118 
    119         if(id%3 != 0)
    120             change(num,id,id-1,'l');
    121         if(id%3 != 2)
    122             change(num,id,id+1,'r');
    123         head++;
    124 
    125     }
    126     if(flag) print(head);
    127     else printf("unsolvable
    ");
    128     return 0;
    129 }
    View Code
     
  • 相关阅读:
    短信猫软件的实现(C#)<八>7bitPDU的解码
    短信猫软件的实现(C#)<七>短信猫(简化测试版)实现
    短信猫软件的实现(C#)<十一>软件实现(完结篇)
    我的EDA课程设计 Verilog HDL 自动售票机的实现
    Linux JNI(1)
    Notes
    Linux 线程属性
    Linux shared lib
    Linux 几个调试命令
    Java工具
  • 原文地址:https://www.cnblogs.com/sdau--codeants/p/3416593.html
Copyright © 2011-2022 走看看