拉丁方块填数

“数独”是当下炙手可热的智力游戏。一般认为它的起源是“拉丁方块”,是大数学家欧拉于1783年发明的。

    如图[1.jpg]所示:6x6的小格被分为6个部分(图中用不同的颜色区分),每个部分含有6个小格(以下也称为分组)。
   
    开始的时候,某些小格中已经填写了字母(ABCDEF之一)。需要在所有剩下的小格中补填字母。

    全部填好后,必须满足如下约束:

    1. 所填字母只允许是A,B,C,D,E,F 中的某一个。

    2. 每行的6个小格中,所填写的字母不能重复。

    3. 每列的6个小格中,所填写的字母不能重复。

    4. 每个分组(参见图中不同颜色表示)包含的6个小格中,所填写的字母不能重复。

    为了表示上的方便,我们用下面的6阶方阵来表示图[1.jpg]对应的分组情况(组号为0~5):
000011
022013
221113
243333
244455
445555
 
    用下面的数据表示其已有字母的填写情况:
02C
03B
05A
20D
35E
53F

    很明显,第一列表示行号,第二列表示列号,第三列表示填写的字母。行号、列号都从0开始计算。

    一种可行的填写方案(此题刚好答案唯一)为:

E F C B D A
A C E D F B
D A B E C F
F B D C A E
B D F A E C
C E A F B D

    你的任务是:编写程序,对一般的拉丁方块问题求解,如果多解,要求找到所有解。

【输入、输出格式要求】

    用户首先输入6行数据,表示拉丁方块的分组情况。

    接着用户输入一个整数n (n<36), 表示接下来的数据行数

    接着输入n行数据,每行表示一个预先填写的字母。

    程序则输出所有可能的解(各个解间的顺序不重要)。

    每个解占用7行。

    即,先输出一个整数,表示该解的序号(从1开始),接着输出一个6x6的字母方阵,表示该解。

    解的字母之间用空格分开。

    如果找不到任何满足条件的解,则输出“无解”

    例如:用户输入:
000011
022013
221113
243333
244455
445555
6
02C
03B
05A
20D
35E
53F

    则程序输出:
1
E F C B D A
A C E D F B
D A B E C F
F B D C A E
B D F A E C
C E A F B D

   再如,用户输入:
001111
002113
022243
022443
544433
555553
7
04B
05A
13D
14C
24E
50C
51A
    则程序输出:
1
D C E F B A
E F A D C B
A B F C E D
B E D A F C
F D C B A E
C A B E D F
2
D C E F B A
E F A D C B
A D F B E C
B E C A F D
F B D C A E
C A B E D F
3
D C F E B A
A E B D C F
F D A C E B
B F E A D C
E B C F A D
C A D B F E
4
D C F E B A
B E A D C F
A D C F E B
F B E A D C
E F B C A D
C A D B F E
5
D C F E B A
E F A D C B
A B C F E D
B E D A F C
F D B C A E
C A E B D F
6
D C F E B A
E F A D C B
A B D F E C
B E C A F D
F D B C A E
C A E B D F
7
D C F E B A
E F A D C B
A D B F E C
B E C A F D
F B D C A E
C A E B D F
8
D C F E B A
F E A D C B
A D B C E F
B F E A D C
E B C F A D
C A D B F E
9
D C F E B A
F E A D C B
A F C B E D
B D E A F C
E B D C A F
C A B F D E

  1 #include<cstdio>
  2  #include<iostream>
  3  using namespace std;
  4  
  5  int last = 36 ;   // 表示还剩余几个空没填 
  6  char a[6][6]={0};//存储结果,0表示结果矩阵中 当前位置还未填
  7  int hor[6]={0},ver[6]={0};//统计行,列中元素个数
  8  bool cla[6][6]={0}; // clag[i][j] 表示分组为 i 的组中 'A'+j 是否使用过  
  9  char group[6][7];
 10  
 11  int seq = 0 ;  //记录结果编号 
 12  
 13  void outPut()
 14  {
 15      seq++;
 16      printf("%d\n",seq);
 17      for(int i=0;i<6;i++)
 18      {
 19          for(int j=0; j<5; j++)
 20          {
 21              printf("%c ",a[i][j]);
 22          }
 23          printf("%c\n",a[i][5]);
 24      }
 25  }
 26  
 27  void searcher()
 28  {
 29      int i,j,k,max,x,y;
 30  
 31      bool f[6]={0};
 32  
 33      if(last==0)
 34      {
 35          outPut();
 36          return;
 37      }
 38      last--;
 39  
 40      //寻找最佳位置---即当前没有填数的坐标所在行和所在列填数之和最多的位置 
 41      max = -1 ;
 42      for(i=0;i<6;i++)
 43      {
 44          if(hor[i]==6)  // 当前行已经填满 
 45              continue;
 46          for(j=0;j<6;j++)
 47              if( a[i][j]==0 && (hor[i]+ver[j])>max )  //每次找当前坐标所在行和所在列填数之和最多的 先填 
 48              {
 49                  max = hor[i]+ver[j];
 50                  x = i;
 51                  y = j;
 52              }
 53      }
 54  
 55      //寻找所有可以填在最佳位置 (x, y) 的允许值    
 56      for(k=0;k<6;k++)
 57      {
 58          if(a[x][k])
 59              f[a[x][k]-'A'] = true ;
 60          if(a[k][y])
 61              f[a[k][y]-'A'] = true ;
 62          if(cla[group[x][y]-'0'][k])
 63              f[k] = true ;
 64      }
 65  
 66      hor[x]++;
 67      ver[y]++;
 68      for(k=0;k<6;k++)
 69          if(f[k]==false)
 70          {
 71              a[x][y] = 'A'+k;
 72              cla[group[x][y]-'0'][k] = true ;
 73              searcher();
 74              cla[group[x][y]-'0'][k] = false ;  // 回溯 
 75          }
 76          
 77      // 回溯
 78      hor[x]--;    
 79      ver[y]--;
 80      a[x][y] = 0 ;
 81      last++;
 82  }
 83  
 84  int main(){
 85      char c;
 86      int n,i,j;
 87      for(i=0;i<6;i++)
 88          scanf("%s",group[i]);
 89      scanf("%d",&n);
 90      c = getchar();
 91      for( ; n ;n--){
 92          i = getchar() - '0' ;
 93          j = getchar() - '0' ;
 94          c = getchar();
 95          a[i][j] = c ;
 96          last--;
 97          hor[i]++;
 98          ver[j]++;
 99          cla[group[i][j]-'0'][c-'A'] = true ;
100          getchar();
101      }
102      searcher();
103      system("pause"); 
104      return 0;
105  }

 

posted @ 2013-05-29 21:30  萧凡客  阅读(2622)  评论(0编辑  收藏  举报