您的位置:首页 > 编程语言 > C语言/C++

N皇后问题 --递归及回溯解决方案

2016-09-28 17:34 323 查看

一:介绍

n 皇后等价于要求在一个 n*n 的棋盘上放置 n 个皇后,使得任何两个皇后都不能被放在同一行或同一列或同一斜线上。

二:算法设计

对于 n 后问题,我们用 n 元组 x[1:n] 表示它的解。其中 x[i] 表示皇后放在棋盘的第 i 行的第 x[i] 列。

由于左上角到右下角的主对角线及其平行线上(斜率为-1),元素2个下标值的差(行号-列号)相等。同理,斜率为+1的斜线上,元素的2个下标值的和(行号+列号)相等。

因此,若两个皇后位置分别为(i, j)和(k,l),且 i - j = k - l 或 i + j = k + l,则说明两个皇后出于同一斜线上。以上两个方程式等价于 i - k = j - l 或 i - k = l - j。

由此可知,只要 |i - k| = |j - l|成立,就表明两个皇后位于同一斜线上。

三:代码实现

#include <iostream>
#include <assert.h>
using namespace std;

const int N_QUEEN = 8;

class queen{
friend int n_queen(int num);             //设为友元函数
private:                                     //方法为私有,增加安全性
bool place(int k);
#ifdef _USE_RECURSION_
void back_track(int t);
#else
void back_track();
#endif
void show()const;
private:
int  num;
int  *x;
long count;
};

bool queen::place(int k)     //检测能否放置
{
for(int i=1; i<k; ++i){     //此处不能等于k,因为是根据之前已经放置好了的皇后判断
if((abs(i-k) == abs(x[i]-x[k])) || (x[i] == x[k]))   //第一个条件检测是否在斜线上,第二个检测是否在同一列
return false;
}
return true;
}

#ifdef _USE_RECURSION_
void queen::back_track(int t)       //递归方法
{
if(t > num){
++count;
show();
}

for(int i=1; i<=num; ++i){      //下标统一从1开始,便于处理
x[t] = i;
if(place(t))
back_track(t+1);
}
}
#else
void queen::back_track()
{
x[1] = 0;                 //初始化为0是一个技巧
int k = 1;
while(k > 0){
x[k] += 1;
while((x[k] <= num) && (!place(k)))   //如果小于边界,且不能放置,继续向下找
x[k] += 1;
if(x[k] <= num){
if(k == num){      //如果到了第八行,成功找到一种情况
++count;
show();
}
else{
++k;
x[k] = 0;
}
}
else
--k;
}
}
#endif

void queen::show()const               //打印每种情况的图
{
for(int i=1; i<=num; ++i){
for(int j=1; j<=num; ++j){
if(x[i] == j)
cout<<'@'<<' ';
else
cout<<'#'<<' ';
}
cout<<endl;
}
cout<<endl;
}

int n_queen(int num)
{
queen que;
que.num = num;
que.count = 0;

int *new_base = new int[num+1];
assert(new_base != NULL);
que.x = new_base;

#ifdef _USE_RECURSION_
que.back_track(1);
#else
que.back_track();
#endif

delete []new_base;
return que.count;
}

int main()
{
int res = n_queen(N_QUEEN);
cout<<res<<endl;
return 0;
}

部分测试结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息