标题:八皇后问题求思路!!!!!
只看楼主
wangwang168
Rank: 1
等 级:新手上路
帖 子:48
专家分:0
注 册:2007-5-8
 问题点数:0 回复次数:8 
八皇后问题求思路!!!!!
在一个八行八列的棋盘里,有八个皇后放在棋盘上,要求放过一个皇后的格子的同行同列以及对角线都不在有其他皇后,只要求解这个问题的具体思路,不要求代码
搜索更多相关主题的帖子: 皇后 思路 棋盘 格子 对角线 
2007-09-17 23:12
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
得分:0 
4个字

递归回溯

Fight  to win  or  die...
2007-09-17 23:22
wangwang168
Rank: 1
等 级:新手上路
帖 子:48
专家分:0
注 册:2007-5-8
得分:0 
楼上的可以说的再具体一点吗

我有一个梦想
2007-09-18 12:23
prodream
Rank: 1
等 级:新手上路
帖 子:32
专家分:0
注 册:2007-9-16
得分:0 

这个是我以前的笔记:
八皇后问题:

初步设计:8层嵌套循环
n为某列,h为所在行数
我假设某点为-1则,该点因为前面的皇后而被约束,
为0,为初始值
为1,表示放有皇后 /*当然这样有很多的多余,例如1,根本不需要设置,形同虚设*/
我的约束是:当a[h][n]=1,则设置a[h][k]=-1;a[h+k][n+k]=-1;a[h-k][n+k]=-1 ,k为0到7 /*会出现很多的问题,可毕竟是初步嘛 :> */
for 对于第一列的每行分析
if 该点适合(适合条件为:该点为0)
BEGIN 保存该点(queuen[1]=h)
. 设置约束
. for 对于第二列的每行进行分析
. if 该点适合
. BEGIN 保存该点
. . 设置约束
. . for ...
. . IF ..
. . BEGIN...
. . .
. . .
. .
. . END
. .
. .
. .
. .
. .
. 清除该次保存点
. 清除该次设置的约束
. END /*将进行对该列的下一行分析*/
.
.清除第一列该次保存点
清除该次设置的约束
END /*将分析第一列的下一行*/

其中有一个特殊的即最后一层的循环 /*特殊是因为,它是最后一层要处理输出,
代码:
for(i_7=0;i_7<8:i_7++)
if(a[i_7][7]==0)
{
queuen[7]=i_7;
循环输出;
}



欢迎加入c语言交流群(27214501),数据结构与算法(27214930)(限非新手进)博客://prodream.blog./
2007-09-18 13:09
prodream
Rank: 1
等 级:新手上路
帖 子:32
专家分:0
注 册:2007-9-16
得分:0 

再次分析:/*分析来在与书上提供的代码的对比来*/
从上面的算法看,它很象递归形式
为什么怎样说了:
1,每次做的事,都是相同的事情
2,很有层次感
3,虽然最后一次的嵌套,有所不一样,但正是递归所需要的/*递归必须向某一个条件靠拢,这样才不会是个死循环递归*/

算法:
queuen(n:分析的第n列)
{for 对第n列的每一行分析
{if 合适
{
queuen[n]=该点所在的行数
设置约束;
if {
这时候分析的是第8行
输出结果
}
ELSE
回调 queuen(++n) /*分析下一列*/

/*到这里是因为,对这列的这行所有的情况已经分析完了*/

清除本次设置的约束
}


欢迎加入c语言交流群(27214501),数据结构与算法(27214930)(限非新手进)博客://prodream.blog./
2007-09-18 13:10
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
得分:0 
你说的要思路啊!

就是这样,走一条路走不通的时候,那么就回到原点,再走下一条路!

Fight  to win  or  die...
2007-09-18 13:10
prodream
Rank: 1
等 级:新手上路
帖 子:32
专家分:0
注 册:2007-9-16
得分:0 

最后的程序代码: /*来在其他的书籍*/
#include "stdio.h"

int col[8],left[15],right[15];
int queen[8];
int n=0;
int sum=0;

void generate()
{
int h,in;
for(h=0;h<=7;h++)
{ if(col[h]&&left[n+h]&&right[n-h+7])
{ queen[n]=h;
col[h]=0;
left[h+n]=0;
right[n-h+7]=0;
n+=1;
if(n==8)
{
sum++;
printf("%d:",sum);
for(in=0;in<=7;in++)
printf("\t\%d",queen[in]);
printf("\n");

}
else generate();
n--;
left[n+h]=1;
right[n-h+7]=1;
col[h]=1;
}
}
}

void main()
{
int c,s;
for(c=0;c<=7;++c)
col[c]=1;
for(s=0;s<=14;++s)
{ left[s]=1;
right[s]=1;
}
printf("行数:\t0\t1\t2\t3\t4\t5\t6\t7\n");
generate();
printf("八皇后的总排法数为:%d",sum);
}


欢迎加入c语言交流群(27214501),数据结构与算法(27214930)(限非新手进)博客://prodream.blog./
2007-09-18 13:11
prodream
Rank: 1
等 级:新手上路
帖 子:32
专家分:0
注 册:2007-9-16
得分:0 

上面的约束有点难: :)资料也没,只好硬着去想拉!

不得不说上面的约束条件太巧了,分三个约束:
1,所在行的约束col[8],即不能在同一行有两个皇后的约束
2,某两条对角线上的约束,left[17],right[17]
3,所在列的约束,这就简单拉
难点是第二中约束:

它将两中对角线的约束,分别映射到两个数组上,但却使得它适合对每一列的约束,它是这样做到的了?

对于不同的列的,真正起约束的是那些下标为:n到n+7到元素
1,对left[n+h]分析:
例如对于第5列,第6行所产生的约束是left[5+6],而对第6行来说,left[11]约束的是这列的第5行
而对第7行来说,left[11]约束的是这列的第4行
画一下图就晓得,这写点都在一个对角线上
2,对right[7-h+n]分析:
例如对于上面的点,产生的约束是right[7-6+5],对于第6行来说,right[6]约束的是这列的第7行 /*6=7-h+6 ->h=7*/
对于第4行来说,right[6]约束的是这列的第5行 /*6=7-h+4 ->h=5*/
画一下图又发现,这些点都在另外的一条对角线上

:)是不是很巧啊,可是怎么发现这爽的规律的了 /*这就要看人的思维本事了,我没想到这来,可能是我还没想到优化,能不能想到这个规律,难说 - -! */
想出来与看不看的懂就是两回事了


欢迎加入c语言交流群(27214501),数据结构与算法(27214930)(限非新手进)博客://prodream.blog./
2007-09-18 13:12
prodream
Rank: 1
等 级:新手上路
帖 子:32
专家分:0
注 册:2007-9-16
得分:0 
写的有点乱,将就一下把!
加入c语言交流群,交流下!

欢迎加入c语言交流群(27214501),数据结构与算法(27214930)(限非新手进)博客://prodream.blog./
2007-09-18 13:13



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-170747-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.984893 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved