回溯求解皇后问题,怎么不对?

surgent 2010-07-22 10:04:44
代码如下,不知道该怎么控制,求真相,谢谢了。

#include <iostream>
#include <cmath>
using namespace std;

#define N 4

int row[N];

void rn_queens(int k);
bool position_ok(int k);

void rn_queens(int k)
{
for (row[k]=0;row[k]<N;row[k]++)
{
if(position_ok(k))
{
if (k==N)
{
for (int i=0;i<N;i++)
{
cout<<row[i]<<","<<i<<endl;
}
cout<<endl;
system("pause");
}
else
{
rn_queens(k+1);
}
}
}
}

bool position_ok(int k)
{
for (int i=0;i<k-1;i++)
{
if(row[k]==row[i]||abs(row[k]-row[i])==k-i)
return false;
}
return true;
}

int main()
{
for (int i=0;i<N;i++)
{
row[i]=0;
}
rn_queens(0);

return 0;
}
...全文
130 点赞 收藏 18
写回复
18 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
超级大笨狼 2010-07-25
可以利用二进制的模板匹配,做到复杂度较低。
回复
surgent 2010-07-25
很感谢贴出o(1)复杂度代码的朋友,不过大家误解了我的意思,我想知道我那么做不对的原因和正确做法,我把书上的伪代码和主要思想发一下吧。《大学算法教程》,作者: (美)Richard Johnsonbaugh Marcus Schaefer 译者: 方存正;曹旻;华明 清华大学出版社:2007年6月第一版.P164--P166

我们来递归地实现n王后问题的回溯法解。关键的函数是rn_queens。当调用rn_queens(k,n)时,在列1到列k-1中王后已妥善放置,而rn_queens试图在列k放置一个王后。如果放置成功,且k等于n,就打印结果。如果只要一个结果的话,算法在这时候就可以结束。但我们要输出所有的结果,所以继续进行下去。如果rn_queens(k,n)在列k成功放置一个王后,而k不等于n,那么它调用rn_queens(k+1,n)试图在下一列放置一个王后。如果rn_queens(k,n)在列k放置一个王后的企图是吧,它就回退至它的调用者rn_queens(k-1,n)试图调整列k-1中的王后。通过调用rn_queens(1,n)得到回溯法的解。
我们利用一个数组row来跟踪王后的位置。row[k]的值是列k中王后所放置的那个行。算法的第一个版本是

n_queens(n){
rn_queens(1,n)
}

rn_queens(k,n){
for row[k]=1 to n
if(position_op(k,n))
if(k==n){
for i=1 to n
print(row[i]+" ")
println()
}
else
rn_queens(k+1,n)
}

position_ok(k,n){
for i=1 to k-1
//abs是绝对值
if(row[k]==row[i]||abs(row[k]-row[i])==k-i)
return false;
return true;
}
回复
macower 2010-07-24

#include<iostream>
using namespace std;
bool b[27],c[27],d[27];
int a[9],i;
void print()
{
int i1;
i++;
cout<<i<<" ";
for (i1=1;i1<=8;i1++)
cout<<a[i1]<<' ';
cout<<endl;
}
void sou(int i)
{
for (int i1=1;i1<=8;i1++)
if (b[i1]&&c[i+i1]&&d[i-i1+8])//运用直线方程求解 ,
{
a[i]=i1;
b[i1]=false;
c[i+i1]=false;
d[i-i1+8]=false;
if (i<8) sou(i+1);
else print();//输出
b[i1]=true;//释放
c[i+i1]=true;
d[i-i1+8]=true;
}
}
int main()
{
for (int o=1;o<=27;o++)//初始化变量
{
b[o]=true;c[o]=true;d[o]=true;
}
i=0;
sou(1);
system("pause");
}
/*
Name: 八皇后问题
Copyright:
Author:

voyage1323

Date: 22-03-08 08:45
Description:递归线性搜索,主要运用排除法,及回溯
*/
回复
surgent 2010-07-24
[Quote=引用 14 楼 xia777xia 的回复:]
?
算法问题怎么到这个区了?
现在csdn跨区服务了……

[/Quote]

这个就是数据结构与算法版阿。。。
回复
p123p456 2010-07-23
有文档说明给大家学习一下理念啊!皇后这个题,我没听说过了!
回复
jvs 2010-07-23
?
算法问题怎么到这个区了?
现在csdn跨区服务了……
回复
o13715182355 2010-07-23
看不懂
回复
[Quote=引用 6 楼 surgent 的回复:]

回3L,row[k]是第k列上皇后的行号。
引用 3 楼 xdxiaofeng 的回复:

row[k] 的值表示第k个皇后放置的位置,也就是k行的 row[k]列 放置的是第k个皇后。

每次循环试探第k个皇后是否能放在row[k]这个位置,如果防止成功,则递归放置第k+1个,直到全部放完。

不过我感觉这这段代码实现有问题,因为它没有回溯的控制。
谁能保证每一次循环都能放下一……
[/Quote]

在这个问题中,行和列是对称的阿。
这么理解怎么会有问题呢?
回复
surgent 2010-07-23
回10L,是《大学算法教程》里面讲的,作者: (美)Richard Johnsonbaugh Marcus Schaefer 译者: 方存正;曹旻;华明

[Quote=引用 10 楼 p123p456 的回复:]

有文档说明给大家学习一下理念啊!皇后这个题,我没听说过了!
[/Quote]
回复
oyzdz1988 2010-07-22
要用二维数组来解决吧~
回复
ycl1314 2010-07-22
顶一个
回复
surgent 2010-07-22
回5L,o(1)的复杂度掩盖了我原来那个算法,书上作为改进有讲你的方法,但o(n)的我没弄懂。。

[Quote=引用 5 楼 fanster28_ 的回复:]

C/C++ code
#include <iostream>

const int N = 8;
int count=0;
//用于记录列 和 两个斜线方向是否存在皇后 check做到O(1)
bool l[N+1]={1,1,1,1,1,1,1,1,1};
bool x[2*N]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
bool y[2*N]={1,1,1,1……
[/Quote]
回复
surgent 2010-07-22
回2L,就是不知道回溯怎么体现。我是看书上这么介绍的,具体实现的时候弄不清了。

[Quote=引用 2 楼 superdullwolf 的回复:]

不知道该怎么控制?
什么意思,问题是什么?没明白你的意思。
[/Quote]
回复
surgent 2010-07-22
回3L,row[k]是第k列上皇后的行号。
[Quote=引用 3 楼 xdxiaofeng 的回复:]

row[k] 的值表示第k个皇后放置的位置,也就是k行的 row[k]列 放置的是第k个皇后。

每次循环试探第k个皇后是否能放在row[k]这个位置,如果防止成功,则递归放置第k+1个,直到全部放完。

不过我感觉这这段代码实现有问题,因为它没有回溯的控制。
谁能保证每一次循环都能放下一个皇后呢?
[/Quote]
回复
fanster28_ 2010-07-22
#include <iostream>

const int N = 8;
int count=0;
//用于记录列 和 两个斜线方向是否存在皇后 check做到O(1)
bool l[N+1]={1,1,1,1,1,1,1,1,1};
bool x[2*N]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
bool y[2*N]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

inline bool check(int n,int i)
{
return l[i]&x[n-i+N]&y[n+i-1];
}

void queens(int n)
{
int i;
if(n==N+1)
count++; //得到解
else
{
for(i=1;i<=N;i++)
{
if(check(n,i))
{
l[i]=0; //选择
x[n-i+N]=0;
y[n+i-1]=0;
queens(n+1);
l[i]=1; //回溯
x[n-i+N]=1;
y[n+i-1]=1;
}
}
}
}

int main()
{
queens(1);
printf("%d\n",count);
return 0;
}
回复
qq120848369 2010-07-22
[Quote=引用 3 楼 xdxiaofeng 的回复:]
row[k] 的值表示第k个皇后放置的位置,也就是k行的 row[k]列 放置的是第k个皇后。

每次循环试探第k个皇后是否能放在row[k]这个位置,如果防止成功,则递归放置第k+1个,直到全部放完。

不过我感觉这这段代码实现有问题,因为它没有回溯的控制。
谁能保证每一次循环都能放下一个皇后呢?
[/Quote]

这里根据你说的,觉得你是理解错了,row[k]的作用不是这个把。
回复
row[k] 的值表示第k个皇后放置的位置,也就是k行的 row[k]列 放置的是第k个皇后。

每次循环试探第k个皇后是否能放在row[k]这个位置,如果防止成功,则递归放置第k+1个,直到全部放完。

不过我感觉这这段代码实现有问题,因为它没有回溯的控制。
谁能保证每一次循环都能放下一个皇后呢?
回复
超级大笨狼 2010-07-22
不知道该怎么控制?
什么意思,问题是什么?没明白你的意思。
回复
发动态
发帖子
数据结构与算法
创建于2007-08-27

3.2w+

社区成员

数据结构与算法相关内容讨论专区
申请成为版主
社区公告
暂无公告