N后问题之回溯法求解

题目:在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 

对于给定的N,求出有多少种合法的放置方法。

同一行,同一列:由题可知,N个皇后只能每行放一个,因此采用n元组x[1:n]表示n后问题的解,其中x[i]表示皇后i放在第i行的第x[i]列。由于不允许将两个皇后放在同一列上,所以x[i]互不相同。 
处在与棋盘边框成45角的斜线上:假设存在a(i,x[i]),b(k , x[k])我们可知ab两点在同意对角线即斜率为正负一的情况下应满足 

i-k=x[i]-x[k]或 i-k=x[k]-x[i]; 由此可得| i-k | = | x[i]-x[k] | 

/*
用n元组x[1:n]表示n后问题的解。x[i]表示皇后i放置在棋盘的第i行的第x[i]列
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int n, x[1000]={0};
long sum;

/*
判断第k个后能不能放在x[k]处
两个皇后不能放在统一斜线上:
若2个皇后放置的位置分别是(i,j)和(k,l),
且 i-j = k -l 或 i+j = k+l,则说明这2个皇后处于同一斜线上。
*/

void OutPut()
{
	int i; 
    for (i = 1; i <= n; ++i)
        printf("(%d, %d) ", i, x[i]);
    printf("\n");
}

int Place(int k)
{
	int j;
    for ( j = 1; j < k; ++j)
        if (abs(k - j) == abs(x[k] - x[j]) || x[j] == x[k])
            return 0;
    return 1;
}

void BackTrack1(int t)
{
	int i;
    //如果t>n说明已经完成一次放置
    if (t > n)
    {
        sum++;
        OutPut();
    }
    else
    {
        for ( i = 1; i <= n; ++i)
        {
            x[t] = i;
            if (Place(t))                   //可以放在i位置处,则继续搜索
                BackTrack1(t + 1);
        }
    }
}


int main()
{
    int nn;
    printf("请输入皇后的个数nn:");
    scanf_s("%d", &nn);
    n = nn;
    sum = 0;
    BackTrack1(1);
    printf("%d\n", sum);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40685275/article/details/80958665