0

我正在设计一个效率极低的幻方求解器,它会告诉您3x3 正方形的解数本质上,我必须将 3x3 数组中的每个元素填充到某个数字(例如 16),然后重置,移动到下一个元素并像两位数增加一样填充它们。我已经设法通过使用 9 个 for 循环来实现这一点,每个元素一个。但是如果我想做一个 5x5 的正方形,我必须写 25 个循环吗?

代码的 for 循环部分如下。有没有办法通过for循环来总结这个和for循环?

for (sq9=1; sq9<17 ; sq9++) {
     for (sq8=1; sq8<17 ; sq8++) {
          for (sq7=1; sq7<17 ; sq7++) {
               for (sq6=1; sq6<17 ; sq6++) {
                    for (sq5=1; sq5<17 ; sq5++) {
                          for (sq4=1; sq4<17 ; sq4++) {
                               for (sq3=1; sq3<17 ; sq3++) {
                                    for (sq2=1; sq2<17 ; sq2++) {
                                         for (sq1=1; sq1<17 ; sq1++) {
                                              if  ( check_the_square() ) count++;
                                                            }}}}}}}}}}

*** EDIT ***

问这个问题 7 年后,我是一家大公司的首席工程师,领导着一个敬业的团队。感谢那些在这里……温柔的人。谢谢你对我的耐心,你的好意走了很长一段路

4

3 回答 3

1

有不止一种方法可以将所有这些概括为任意数量的正方形,但我想到的第一个方法是将所有正方形存储在一个数组中,并像递增一个用数字写出的数字一样递增它们。

首先,让我们用一些易于编辑的常量抽象出正方形的数量及其值的范围:

#define NUM_SQUARES 9
#define MIN_VAL     1
#define MAX_VAL     16

现在,在您正在执行所有这些操作的任何函数中,声明一个 s 数组int并将它们全部设置为MIN_VAL

int squares[NUM_SQUARES];
for (int i=0; i<NUM_SQUARES; i++) {
    squares[i] = MIN_VAL;
}

现在,我们将如何增加正方形?简单:在第一个值上加一个;如果溢出MAX_VAL,将其设置为MIN_VAL并继续下一个方块。如果它没有溢出,停止,我们可以检查当前的配置。如果所有的方格都溢出并且我们移过了数组的末尾,我们知道我们已经处理了所有可能的方格配置,我们可以结束整个事情。

这在代码中会是什么样子?像这样的东西:

int i = 0;
do {
    if (check_the_square()) count++;
    for (i=0; i<NUM_SQUARES; i++) {
        squares[i]++;
        if (squares[i] > MAX_VAL) {
            squares[i] = MIN_VAL;
        } else {
            break;
        }
    }
} while (i < NUM_SQUARES);
于 2013-04-04T20:47:58.893 回答
1

有一些库可以生成所有排列,但如果你想自己做,你可以通过一个值数组来管理它,从所有值开始为 0 并以所有值结束为 16。

const int SIZE = 3;
const int START_VALUE = 1;
const int FINAL_VALUE = 16;
int elements[3][3] = {START_VALUE};

然后定义一组函数来处理该数组。

// Will return false when all combinations have been tried.
bool has_next_permutation(int array[SIZE][SIZE]) {
    for (int i = 0; i < SIZE; ++i) {
        for (int j = 0; j < SIZE; ++j) {
            if (array[i][j] != START_VALUE) {
                // We're not back to all elements being 0, so we're not done.
                return true;
            }
        }
    }
    return true;
}

// Gets the next permutation.
// Increase the first element by 1, and if it hits 17, reset it and
// increase the second element by 1, etc.
void get_next_permutation(int array[SIZE][SIZE]) {
    for (int i = 0; i < SIZE; ++i) {
        for (int j = 0; j < SIZE; ++j) {
            array[i][j]++;
            if (array[i][j] <= FINAL_VALUE) {
                // Hasn't reached the final value yet.
                return;
            }
            array[i][j] = 0;
        }
    }
}

然后在循环中使用它,例如:

do {
    check_the_square();
    get_next_permutation(elements);
} while (has_next_permutation(elements));   
于 2013-04-04T20:57:10.953 回答
0

使用一个数组来替换你的sq#和一个计算下一次迭代的小算法......在这里你基本上需要一个 +1 运算符来用 9 位数编写的 base-17 中的数字......

  char sq[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  int l = 8;
loop:
  if (l==-1) goto end;
  if (++sq[l]==18) { sq[l--]=1; goto loop; }
  check_the_square();
  l = 8;
  goto loop;
end:
  ...
于 2013-04-04T20:47:27.670 回答