您的位置:首页 > 其它

回溯经典-n皇后问题

2010-02-03 11:11 323 查看
题目大意:

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

http://zh.wikipedia.org/wiki/八皇后问题 在维基百科上有详细的描述。

算法思路:

递归方法和非递归方法实现如下:

/*
递归方法实现,输入n,输出所有的可能的皇后分布
*/
#include <iostream>
#define MAXN 105
using namespace std;
int array[MAXN] = {0};
int outarray[MAXN][MAXN] = {0};
int N;
int num = 0;
//输出结果
void output()
{
cout << num << endl;
for(int i = 0; i< N; i++)
{
for(int j = 0; j< N; j++)
{
cout << '|';
outarray[i][j]? cout << 'Q': cout << ' ';
}
cout <<'|'<< endl;
}
cout << endl;
}
//通过与前面0->x-1个皇后比较,判断(x,y)位置是否安全
bool place(int x, int y)
{
for(int i = 0; i < x; i++)
{
int j = array[i];
if(i == x || j == y) return false;  //同行,同列都是不可以的
if(x-y == i-j || x+y == i+j) return false; //对角线上也是不允许的
}
return true;
}
//处在第x行时的状态,这是回溯的主线,从0行到n-1行为止
void nqueue(int x)
{
if(x >= N)  //当到达最后一行之后,输出n个皇后的分布情况
{
num++;
output();
}
else       //当还没有到达最后一行之时,继续往下一行递归,枚举y所有的可能情况
{
for(int y = 0; y < N; y++)
{
array[x] = y;
outarray[x][y] = 1;
if(place(x, y)) nqueue(x+1);
outarray[x][y] = 0;
}
}
}
int main()
{
cin >> N;
nqueue(0);
return 0;
}


//迭代实现:
#include <stdio.h>
#include <stdlib.h>
#define N 8

int x
;
int sum;
bool place(int i)
{
int j=0;
for(j =0;j<i;j++)
if(abs(x[i]-x[j]) == abs(i-j)|| x[j] == x[i])
return false;
return true;
}
void queen()
{
x[0]=-1;//初始化第一个皇后的坐标,在第一行第一列
int k = 0;//表示列号
while(k>=0)
{
x[k]+=1;//此时对于第k个皇后,列号向右移动,表示,当回溯到这一层时0~x[k]-1已经探索过了,接着往后探索
while(x[k]<N && !place(k)) x[k]++;//对于第k个皇后,找到一个合适的位置
if(x[k]<N)
{
if(k==N-1)
sum ++;//如果k已经是最后一个皇后,则找到了一个方案
else// 否则,继续探索下一个皇后
{
k++;
x[k] = -1;
}
}
else//对于第k个皇后,没有找到一个合适的位置,这相对于搜索树的第k层,于是对于这个节点的子树不再搜索,回溯到上一层
k--;
}
}
int main()
{
queen();
printf("sum = %d/n",sum);
}


参考:

http://zh.wikipedia.org/wiki/八皇后问题

http://blog.csdn.net/clearriver/archive/2009/06/21/4287283.aspx

http://www.cppblog.com/3522021224/archive/2007/06/21/26785.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: