N皇后问题

http://acmpj.zstu.edu.cn/JudgeOnline/showproblem?problem_id=2793

N皇后问题(非递归实现及递归实现(C++))

/*

Description

检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子。

上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:这只是跳棋放置的一个解。请遍一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(这题目大家不要直接输出答案,这样就没意义了)。

Input:一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。

Output:前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

Sample Input

6

Sample Output

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

*/

 

//可行则进,不行则换,换不成则退

 

C++实现:

//数组row、diag、vdiag用来标记该列,及对角线是否已经放置了皇后

#include <iostream>
using namespace std;
void NonrecursiveNQueen (int n);
void RecursiveNQueen (int n);
int main(void)
{
    int n = 0;
    
    while (cin >> n)
    {
        NonrecursiveNQueen(n);
        RecursiveNQueen(n);
    }
    return 0;
}
void NonrecursiveNQueen (int n)
{
    if (n < 1)
    {
        return;
    }
    bool *row = new bool[2*n+2];
    bool *diag = new bool[2*n+2];
    bool *vdiag = new bool[2*n+2];
    int * x = new int[n+1];
    int k, ct;
    k=2*n+2;
    for (int i=0; i < k; ++i)
    {
        row[i] = diag[i] = vdiag[i] = false;
    }
    ct = x[1] =0;k = 1;
    while(k>0){
        x[k]++;
        while (x[k] <= n && (row[x[k]] || diag[x[k]+k] || vdiag[x[k]-k+n]))
        {
            x[k]++;
        }
        if(x[k]<=n)
        {
            if(k==n){
                ct++;
                if (ct < 4)
                {
                    for(int i = 1; i <= n; ++i)
                    {
                        cout << x[i] << ' ';
                    }
                    cout << endl;
                }
            }
            else
            {
                row[x[k]] = diag[x[k]+k] = vdiag[x[k]-k+n] = true;
                x[++k]=0;
            }
        }
        else if (--k)
        {
            row[x[k]]= diag[x[k]+k]= vdiag[x[k]-k+n]= false;
        }
    }
    printf("%d\n",ct);
    delete[] row;
    delete[] diag;
    delete[] vdiag;
    delete[] x;
}
void MyNQueen(int *x, bool *row, bool *diag, bool *vdiag, int n, int k, int &ct)
{
    if (k > n)
    {
        ++ct;
        if (ct < 4)
        {
            for(int i = 1; i <= n; ++i)
            {
                cout << x[i] << ' ';
            }
            cout << endl;
        }
    }
    else
    {
        for (int i = 1; i <=n; ++i)
        {
            x[k] = i;
            if (!(row[x[k]] || diag[x[k]+k] || vdiag[x[k]-k+n]))
            {
                row[x[k]] = diag[x[k]+k] = vdiag[x[k]-k+n] = true;
                MyNQueen(x, row, diag, vdiag, n, k + 1, ct);
                row[x[k]] = diag[x[k]+k] = vdiag[x[k]-k+n] = false;
            }
        }
    }
    return;
}
void RecursiveNQueen (int n)
{
    if (n < 1)
    {
        return;
    }
    bool *row = new bool[2*n+2];
    bool *diag = new bool[2*n+2];
    bool *vdiag = new bool[2*n+2];
    int *x = new int[n+1];
    int ct = 2*n+2;
    for (int i=0; i < ct; ++i)
    {
        row[i] = diag[i] = vdiag[i] = false;
    }
    ct = 0;
    MyNQueen(x, row, diag, vdiag, n, 1, ct);
    cout << ct << endl;
    delete[] row;
    delete[] diag;
    delete[] vdiag;
    delete[] x;
}

/*
功能: 求解放置8皇后方案的个数。
输入:
    int:皇后的个数
返回:
    int:放置8皇后方案的个数
*/
int PlaceQueenMethodNum(int n)
{
    /*在这里实现功能*/
    if (n < 1)  
    {  
        return 0;  
    }

    bool *row=new bool[n];
    bool *m_diag=new bool[2*n];
    bool *v_diag=new bool[2*n];

    int *col=new int[n];
    int total=0;
    int k=0;

    for(int i=0;i<n;++i){
        row[i]=false;
        m_diag[i]=m_diag[i+n]=false;
        v_diag[i]=v_diag[i+n]=false;
    }

    col[k]=-1;
    while(k>=0){
        col[k]++;
        while(col[k]<n&&(row[col[k]]||m_diag[col[k]-k+n]||v_diag[col[k]+k])){
            col[k]++;
        }
        if(col[k]<n){
            if(k==n-1){
                total++;
            }else{
                row[col[k]]=m_diag[col[k]-k+n]=v_diag[col[k]+k]=true;
                col[++k]=-1;
            }
        }else if(k--){
            row[col[k]]=m_diag[col[k]-k+n]=v_diag[col[k]+k]=false;
        }
    }

    delete[] col;
    delete[] v_diag;
    delete[] m_diag;
    delete[] row;

    return total;
}

 

C非递归实现:

//数组a、b、c用来标记该列,及对角线是否已经放置了皇后
#include<stdio.h>
#define M 103
int main(void)
{
    int i,k,n,ct,x[M/3],a[M],b[M],c[M];
    while(scanf("%d",&n)!=EOF){
        ct=x[1]=0;k=2*n+1;
        for(i=0;i<k;i++)a[i]=b[i]=c[i]=0;
        k=1;
        while(k>0){
            x[k]++;
            while(x[k]<=n&&(a[x[k]]||b[x[k]+k]||c[x[k]-k+n]))x[k]++;
            if(x[k]<=n)
                if(k==n){
                    ct++;
                    if(ct<4){for(i=1;i<=n;i++)printf("%d ",x[i]);printf("\n");}
                }
                else{a[x[k]]=b[x[k]+k]=c[x[k]-k+n]=1;k++;x[k]=0;}
            else if(--k){a[x[k]]=b[x[k]+k]=c[x[k]-k+n]=0;}
        }
        printf("%d\n",ct);
    }
    return 0;
}

Java:

package com.coding.test;

import java.util.Arrays;

public class NQueensProblem {

    public static void main(String[] args) {
        System.out.println("args.length: " + args.length);
        System.out.println("args: " + Arrays.toString(args));
        if (args.length < 1) {
            System.out.println("Usage: NQueensProblem 8");
            return;
        }

        NQueensProblem queen = new NQueensProblem(Integer.valueOf(args[0]));

        int solutionCount;
        System.out.println("recursiveSolution:");
        solutionCount = queen.recursiveSolution();
        System.out.printf("recursiveSolution solutionCount: %s\n", solutionCount);

        System.out.println("nonRecursiveSolution:");
        solutionCount = queen.nonRecursiveSolution();
        System.out.printf("nonRecursiveSolution solutionCount: %s\n", solutionCount);
    }

    private int[] x;

    private int sum = 0;

    private int problemSize;

    NQueensProblem(int n) {

        problemSize = n;
        sum = 0;
        x = new int[n + 1];
    }

    private void nonRecursiveBackTrack() {
        int k = 1;
        x[k] = 0;
        while (k > 0) {
            x[k] += 1;
            while ((x[k] <= problemSize) && !place(k)) {
                x[k]++;
            }
            if (x[k] <= problemSize) {
                if (k == problemSize) {
                    sum++;
                    System.out.printf("solution %d: %s\n", sum, Arrays.toString(x));
                } else {
                    k++;
                    x[k] = 0;
                }

            } else {
                k--;
            }
        }
    }

    private int nonRecursiveSolution() {
        sum = 0;
        nonRecursiveBackTrack();

        return sum;
    }

    private boolean place(int k) {
        for (int i = 1; i < k; i++) {
            if ((Math.abs(i - k) == Math.abs(x[i] - x[k])) || (x[i] == x[k])) {
                return false;
            }
        }
        return true;
    }

    private void recursiveBackTrack(int k) {
        if (k > problemSize) {
            sum++;
            System.out.printf("solution %d: %s\n", sum, Arrays.toString(x));
            return;
        }

        for (int i = 1; i <= problemSize; i++) {
            x[k] = i;
            if (place(k)) {
                recursiveBackTrack(k + 1);
            }
        }
    }

    private int recursiveSolution() {
        sum = 0;
        recursiveBackTrack(1);

        return sum;
    }

}

or

package com.coding.test;

import java.util.Arrays;

public class NQueensProblem {

    public static void main(String[] args) {
        System.out.println("args.length: " + args.length);
        System.out.println("args: " + Arrays.toString(args));
        if (args.length < 1) {
            System.out.println("Usage: NQueensProblem 8");
            return;
        }

        NQueensProblem queen = new NQueensProblem(Integer.valueOf(args[0]));

        int solutionCount;
        System.out.println("recursiveSolution:");
        solutionCount = queen.recursiveSolution();
        System.out.printf("recursiveSolution solutionCount: %s\n", solutionCount);

        System.out.println("nonRecursiveSolution:");
        solutionCount = queen.nonRecursiveSolution();
        System.out.printf("nonRecursiveSolution solutionCount: %s\n", solutionCount);
    }

    private int[] x;

    private int sum = 0;

    private int problemSize;

    NQueensProblem(int n) {

        problemSize = n;
        sum = 0;
        x = new int[n];
    }

    private void nonRecursiveBackTrack() {
        int k = 0;
        x[k] = -1;
        while (k > -1) {
            x[k] += 1;
            while ((x[k] < problemSize) && !place(k)) {
                x[k]++;
            }
            if (x[k] < problemSize) {
                if ((k + 1) == problemSize) {
                    sum++;
                    System.out.printf("solution %d: %s\n", sum, Arrays.toString(x));
                } else {
                    k++;
                    x[k] = -1;
                }

            } else {
                k--;
            }
        }
    }

    private int nonRecursiveSolution() {
        sum = 0;
        nonRecursiveBackTrack();

        return sum;
    }

    private boolean place(int k) {
        for (int i = 0; i < k; i++) {
            if ((Math.abs(i - k) == Math.abs(x[i] - x[k])) || (x[i] == x[k])) {
                return false;
            }
        }
        return true;
    }

    private void recursiveBackTrack(int k) {
        if (k == problemSize) {
            sum++;
            System.out.printf("solution %d: %s\n", sum, Arrays.toString(x));
            return;
        }

        for (int i = 0; i < problemSize; i++) {
            x[k] = i;
            if (place(k)) {
                recursiveBackTrack(k + 1);
            }
        }
    }

    private int recursiveSolution() {
        sum = 0;
        recursiveBackTrack(0);

        return sum;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值