《八皇后问题》解题报告

标签:
深搜八皇后acmit |
一、
这里八皇后问题使用递归式深搜解法。要点在于:首先深搜方法得出部分排列,再判断这样的排列是否满足不互相攻击,满足则进行下一阶段搜索,否则搜索本阶段下一个部分排列,至本阶段搜索完则回溯。
二、
主要的两个难点是深搜函数和判断是否会相互攻击。前者已经有详细的讲解,故不做过多叙述;主要对后者做讨论。我们把问题作简化:很容易知道,对于每行与每列,有且只有一个皇后。如果对64个点选出8个做深搜进行判断,既不利于判断函数编写,也不利于程序的效率(程序需要运行64!/56!次)。既然具备简化问题的条件,我们应该积极地寻求解决问题的方法。我们利用下标存储行号,建立数组存储每一行对应的列,就极大地简化了数据量。
接下来是判断函数的编写。做一个简单的推理:添加一个新的皇后时,只需检查它与之前的皇后是否有冲突。同时由于新皇后一定在旧后的下边,故简化后我们只需判断新皇后是否在如图线上:(为节省时间简化问题至6个皇后)(黄色六芒星表示皇后,红色圆表示攻击范围)。
http://s13/bmiddle/bebf89f3tde02e9fbbf1c&690
对问题再次做简化以适应于简易的算法:我们得到需要判断的某行,在这样的一行,对于某个皇后,最多只有两个位置可被攻击到。进行一次循环并判断,即可得到所求的解。这样的点可以用简单的几何方法求得。
至此把判断的问题难点已经攻破。
三、
如下:
#define STATUS
int
#define Q
8
#include
#include
#include
int wer=0,ans[100];//wer存储题解个数 ans数组存储解并即时输出
STATUS vis[100];
//vis 数组表示当前的访问状态
void
dfs(int);
void
print();
int judge(int,int);//判断函数声明
void print()
{
}
STATUS judge(int n,int p)//这里判断是否放置的皇后会互相攻击
{
}
void dfs(int n)
{
}
int main()
{
}
四、
这是我第一次做这样的解题报告,排版什么的都很渣,希望勿怪。部分思路沿用自网上及此前的知识储备,还有很多想法是自己想到的。
值得注意的是,与上一次的全排列不同,主函数调用dfs函数时参数是1,否则无法产生正确结果。计算机世界千变万化,有时候我们需要存储更多的数据来减少计算(动态规划等);有时候我们却在简化存储方式的同时也简化了问题。我们致力于做更好的算法,这条路任重道远,我们会继续下去!
黑科大Acm小组
姜志鹏
2013.5.27