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;
}
}