Hlg 1049 【广搜+康拓展开】.cpp

题意:

  如下图所示,从上到下从左到右,给出3*3矩阵的数字摆放起始情况..

  输出最少经过几步可以把这个矩阵变成0123456789的形式..其中0表示空格..

  如果无法变成0123456789就输出NO..

   Hlg 1049 【广搜+康拓展开】.cpp

 

思路:

  求最少几步可以变成0123456789一下子就想到了广搜..

  但是用广搜的时候会需要一个数组vis[]记录当前状态已经搜过了,不需要继续搜..但是用vis[0][1][2][3][4][5][6][7][8][9]这样的话会超内存..

  所以就用康拓展开来记录状态..

  

  康拓展开就是通过公式计算出该数在总序列里的序号..

  

  举个例子
  123这个排列
  有如下排列方式
  排列数 序号
  123 1
  132 2
  213 3
  231 4
  312 5
  321 6
  其实就是全排列的字典序
   用那个公式得到123的值就是1

 

  根据序号得到该排列数..一个排列数表示了八数码的状态..

 

  广搜的时候就把0123456789当成是初始状态..看一下是否可以搜到结果状态..

  可以就输出最小值..如果初始状态就是0123456789就直接输出0..

  广搜的时候就看一下可以往哪里移动且移动后的状态是没有出现过的..

  最后就可以得到最少使用的次数了..

  

 

Tips:

///X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!
  康拓展开..
  开一个vis[9!]的数组就可以记录所有的状态了..
  
康拓展开运用举例..

  0213
  X=0*3! + 1*2! + 0*1!
  那个an表示从右向左数第N个数字后面有几个比他小的
  例如
  54321
  a5 = 4

 

 

Code:

View Code
  1 #include <iostream>

  2 #include <algorithm>

  3 #include <stdio.h>

  4 #include <queue>

  5 #include <cstring>

  6 using namespace std;

  7 #define clr(x) memset(x, 0, sizeof(x))

  8 

  9 ///X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

 10 

 11 struct Num

 12 {

 13     char num[10];

 14     int cnt;

 15 };

 16 

 17 bool vis[363000];

 18 int cnt[363000];

 19 int cha[4] = {-3, -1, 1, 3};

 20 int qpl[9] = {40320, 5040, 720, 120, 24, 6, 2, 1, 1};

 21 int fac[10]={1,1,2,6,24,120,720,5040,40320,362880};

 22 int kt(char*s)

 23 {

 24     int i,j,t;

 25     int num=0;

 26     for(i=0;i<8;i++)

 27     {

 28         t=0;

 29         for(j=i+1;j<9;j++)

 30             if(s[j]<s[i])

 31                 t++;

 32             num+=fac[8-i]*t;

 33     }

 34     return num;

 35 }

 36 

 37 int check(char *arr)

 38 {

 39     for(int i = 0; i < 9; ++i)

 40     if(arr[i] == '0') return i;

 41 }

 42 

 43 void bfs() {

 44     queue<Num> Q;

 45     Num tmp, tmp1;

 46     strcpy(tmp.num, "012345678"), tmp.cnt = 0;

 47     Q.push(tmp);

 48     tmp = Q.front();

 49     int tmpn;

 50     vis[0] = true;

 51     int res = 0;

 52     while(!Q.empty()) {

 53         tmp = Q.front();

 54         int x = kt(tmp.num);

 55         Q.pop();

 56         int pos = check(tmp.num);

 57         if (pos >= 3){

 58             swap(tmp.num[pos],tmp.num[pos-3]);

 59             tmpn = kt(tmp.num);

 60             if (!vis[tmpn]){

 61                 cnt[tmpn] = cnt[x]+1;

 62                 if (cnt[tmpn]>res)

 63                 res = cnt[tmpn];

 64                 vis[tmpn] = true;

 65                 Q.push(tmp);

 66             }

 67             swap(tmp.num[pos],tmp.num[pos-3]);

 68         }

 69         if (pos <= 5){

 70             swap(tmp.num[pos],tmp.num[pos+3]);

 71             tmpn = kt(tmp.num);

 72             if (!vis[tmpn]){

 73                 cnt[tmpn] = cnt[x]+1;

 74                 if (cnt[tmpn]>res)

 75                 res = cnt[tmpn];

 76                 vis[tmpn] = true;

 77                 Q.push(tmp);

 78             }

 79             swap(tmp.num[pos],tmp.num[pos+3]);

 80         }

 81         if (pos%3!=0){

 82             swap(tmp.num[pos],tmp.num[pos-1]);

 83             tmpn = kt(tmp.num);

 84             if (!vis[tmpn]){

 85                 cnt[tmpn] = cnt[x]+1;

 86                 if (cnt[tmpn]>res)

 87                 res = cnt[tmpn];

 88                 vis[tmpn] = true;

 89                 Q.push(tmp);

 90             }

 91             swap(tmp.num[pos],tmp.num[pos-1]);

 92         }

 93         if (pos%3 != 2){

 94             swap(tmp.num[pos],tmp.num[pos+1]);

 95             tmpn = kt(tmp.num);

 96             if (!vis[tmpn]){

 97                 cnt[tmpn] = cnt[x]+1;

 98                 if (cnt[tmpn]>res)

 99                 res = cnt[tmpn];

100                 vis[tmpn] = true;

101                 Q.push(tmp);

102             }

103             swap(tmp.num[pos],tmp.num[pos+1]);

104         }

105     }

106 }

107 

108 int main()

109 {

110     clr(vis);

111     clr(cnt);

112     queue<Num> Q;

113     bool flag;

114     bfs();

115     char num[10];

116     while(EOF != scanf("%s", num)) {

117         int tmp = kt(num);

118         if(cnt[tmp] || tmp ==0) printf("%d\n", cnt[tmp]);

119         else puts("NO");

120     }

121     return 0;

122 }

 

链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1049

你可能感兴趣的:(cpp)