如何在不使用相同列,行的相同颜色的情况下绘制具有n种不同颜色的r x r字段

时间:2017-06-04 14:45:19

标签: c algorithm recursion memoization

最近,我遇到了这个问题,因为时间的推移我无法解决。

'创建一个程序,用于解答使用n种不同颜色的r场绘制r的方法,而不使用相同行,同一列的相同颜色。'

我为它编码了,但是只用6种颜色的6乘6场就需要超过30分钟。

所以,我想到了多维记忆,但我没有想法在我的代码中添加memoization数组。

请帮助我更快地修改代码或建议新方式。

#include<stdio.h>
#include<stdlib.h>
int check[100][100], scheck[100][100], n, r;  
long long cnt; 
void arr(int x, int y) { 
   int i, k=0; 
   for (int j = 0; j < n; j++) { //about n colors 
      if (check[y][j] == 0 && scheck[x][j] == 0) { //if there is no j th color in same row and column
         check[y][j] = 1; // check 'there is j th color in y th row, x th column
         scheck[x][j] = 1; // to make same effect with inputing j at virtual field[y][x]
         if (x == r - 1) { // if x th column is the end of right
             if (y == r - 1) cnt++; // if y th column is the bottom, count this 
             else arr(0, y + 1); // else fill next row, first column 
         } 
         else arr(x + 1, y); // else fill next right square
         check[y][j] = 0; // check 'there is no j th color in y th row, x th column
         scheck[x][j] = 0; // to make same effect with erasing j virtual field[y][x]
      } 
   } 
   return; 
} 
void main() { 
    printf("Input n, r (paint r x r field with n colors, same color cannot be used in same column and row) \n: "); 
    scanf("%d %d", &n, &r); 
    arr(0, 0); 
    printf("There are %ld ways to paint.\n", cnt); 
} 

1 个答案:

答案 0 :(得分:0)

这也是广义exact cover问题的一个例子,一类问题包括熟悉的例子,如数独谜题(你可以注意到相似性)和N皇后问题。这个问题是NP完全的,所以没有一个超级有效的算法,但由于Donald Knuth,有一个称为Algorithm X的规范解决方案。

要将您的问题转换为精确封面的语言,请注意有r ^ 2 + 2rn约束必须恰好满足0或1次:对于行和列0&lt; = i,j&lt; r,只有一个条目,并且对于每个0&lt; = k&lt; r和0&lt; = c&lt; n,在行(或列)k中有一个颜色c的条目。表中有nr ^ 2个可能的条目,即在第i行和第j列放置颜色c。这些中的每一个满足两个约束(即,颜色c和行i,行j处的颜色c),而不满足任何其他约束。因此,您可以构造一个包含nr ^ 2行和2rn列的矩阵。解决此表的确切覆盖问题只是有点过度限制,因为它要求每个n行中的每一种颜色出现在每行和每列一次,而不是最多一次。这种差异是使问题成为广义精确覆盖问题的原因,并且通过添加2rn簿记行来解决,每个行在与行/列颜色条件对应的2rn约束中的一个中恰好具有1。