仅在1秒内解决16-Queens问题

时间:2015-08-23 02:03:34

标签: algorithm backtracking n-queens

我应该在1秒内解决16-Queens Problem。 我使用了如下的回溯算法。 当N小于13时,此代码足以在1秒内解决N-Queens问题。 但是如果N大于13则需要很长时间。

我该如何改进?

#include <stdio.h>
#include <stdlib.h>

int n;
int arr[100]={0,};
int solution_count = 0;

int check(int i) 
{ 
    int k=1, ret=1;
    while (k < i && ret == 1) {
        if (arr[i] == arr[k] ||                 
            abs(arr[i]-arr[k]) == abs(i-k))     
            ret = 0; 
        k++;
    }
    return ret;
}

void backtrack(int i) 
{
    if(check(i)) {
        if(i == n) {
            solution_count++;
        } else {
            for(int j=1; j<=n; j++) {
                arr[i+1] = j;
                backtrack(i+1);
            }
        }
    }
}

int main() 
{ 
    scanf("%d", &n);  
    backtrack(0);
    printf("%d", solution_count);
}

2 个答案:

答案 0 :(得分:4)

你的算法几乎没问题。一个小的改变可能会给你足够的时间来提高解决方案的速度。此外,还有一个数据结构更改,可以让您进一步缩短时间。

首先,稍微调整算法:而不是一直等待检查,直到你放置所有N个皇后,提前检查:每次你要放置一个新女王时,检查另一个女王是否是在进行arr[i+1] = j;分配之前占据相同的列或相同的对角线。这将为您节省大量的CPU周期。

现在你需要加快检查下一个女王。为此,您必须更改数据结构,以便可以在没有任何循环的情况下执行所有检查。以下是如何做到这一点:

  • 您有N
  • 您有N
  • 您有2N-1上升对角线
  • 您有2N-1下降对角线

由于没有两个皇后可以在四个&#34;尺寸中的任何一个中占据相同的位置。上面,你需要一个最后三件事的布尔值数组;保证行不同,因为代表行的i backtrack参数保证不同。

N最多为16,2N-1最多为31,因此您可以将uint32_t用于您的位阵列。现在,您可以通过按位和c应用列位掩码和&来检查是否采用了列1 << c。对角位掩码也是如此。

注意:在一秒钟内完成16皇后问题会相当棘手。 very highly optimized program在800 MHz PC上在23秒内完成。 3.2 GHz应该可以提供大约4倍的加速,但是获得解决方案大约需要8秒。

答案 1 :(得分:1)

我会将while (k < i && ret == 1) {更改为while (k < i) {
而不是ret = 0;return 0;

(这将在每次迭代时保存一个检查。可能是你的编译器仍然执行此操作,或者其他一些性能技巧,但这可能会有所帮助。)