关于8个女王问题算法的一些疑问

时间:2013-04-01 15:24:14

标签: algorithm theory n-queens

我正在研究8皇后问题,我认为以下算法可以解决这个问题(但似乎不正确)

我的算法在8X8棋盘上以这种方式工作:

  1. 一开始就把女王放在董事会的随机位置
  2. 将当前女王的水平线,垂直线和两条对角线上的位置标记为无法使用。
  3. 将另一位女王放置在任何仍然空闲的位置
  4. 迭代此过程(从第2点开始),直到主板上有可用的位置
  5. 我在纸上试过这个解决方案但是,我经常只能放7个女王而不是女王......

    所以我认为这个解决方案可以放置一些不能互相吃掉的皇后,但是如果我使用的是nXn板,我总能放置8个皇后... < / p>

    是真的吗?

    TNX

    安德烈

2 个答案:

答案 0 :(得分:3)

为您的算法添加回溯。如果将第7位女王放置在没有第8位空间的位置,那么对于第7位女王来说这是一个不好的位置。所以删除它并为它选择一个不同的位置。如果第7位女王的位置用完,这意味着第6位女王处于不利位置等等。

答案 1 :(得分:3)

关于回溯,

@miorel 是完全正确的。为了好玩,我尝试使用简单的递归算法在C / C ++中解决这个暴力问题,只需一个简单的优化:

我们知道,对于任何给定的问题大小N,每个女王将在一个单独的列中。所以我们甚至不尝试其他专栏。所以这个想法是这样的:

  • 每个女王都有自己的专栏,所以女王1排在第1列,女王2排在第2列,等等。
  • 因此,目标实际上是为每位女王选择一排。从第一个女王开始,让我们依次尝试每一行。我们通过在可能的行中放置一个女王,然后进行递归调用以放置第二,第三和第四女王来做到这一点。
  • 在检查放置是否兼容时,我们只需要检查a)同一行中是否有女王,以及b)是否有对角线皇后。

    #include <stdlib.h>
    #include <stdio.h>
    
    int solveQueens(int queenIndex, int sz, int * positions) {
        for (int i=0; i<sz; i++) {
            int valid = 1;
            for (int j=0; j<queenIndex; j++) {
                int diff = queenIndex-j;
                if ( 
                        (positions[j]==i)
                    ||  (positions[j]+diff == i) 
                    ||  (positions[j]-diff == i)
                ) {
                    valid = 0;
                    break;
                }
            }
    
            if (valid) {
                positions[queenIndex]=i;
                if (queenIndex < sz-1) {
                    // Recursive call
                    int res = solveQueens(queenIndex+1, sz, positions);
                    if (res) 
                        return 1;
                } else {
                    return 1;
                }
            }
        }
        return 0;
    }
    
    void printQueens(int sz, int * positions) {
        for (int i=0; i<sz; i++) {
            printf("%c%d ", (char)(i+(int)'A'), positions[i]+1);
        }   
    }
    
    void queens(int sz) {
        int * positions = (int *)malloc(sizeof(int)*sz);
        if (solveQueens(0, sz, positions)) {
            printQueens(sz, positions);
        } else {
            printf("No solutions found\n");
        }
        free(positions);
    }
    
    int main() {
        queens(24);
        return 0;
    }
    

我确信这不是最佳算法,但在24秒的电路板尺寸下工作时间不到1秒。