人工智能-实验2
计科210x 甘晴void
一、实验目的
-
求解约束满足问题
-
使用回溯搜索算法求解八皇后问题
二、实验平台
三、实验内容
3.0 题目要求
回溯搜索算法
搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。
回溯 是搜索算法中的一种控制策略。
基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。
编程要求
在右侧编辑器中完成void searchh(int i)
函数,求出八皇后问题共有多少种算法。
测试说明
平台会对你编写的代码进行测试:
预期输出:92
3.1 A*算法原理
- 递归搜索:从第一行开始,逐行放置皇后,每行放置一个皇后,直到所有皇后都被放置。
- 选择合适位置:对于当前行的每一列,检查是否能够放置皇后。如果当前位置合法(不与已放置皇后冲突),则放置皇后,继续递归地处理下一行。
- 回溯选择:如果当前位置无法放置皇后,说明之前的选择不正确,需要回溯到上一步重新选择位置。
- 标记冲突位置 :为了避免皇后之间的冲突,需要用数组
b
、c
、d
来标记已经放置的皇后位置所占据的列和对角线。 - 结束条件:当成功放置了八个皇后(即当前行数达到 8)时,找到了一组解,计数器增加,并返回上一层继续搜索其他解。
3.2 算法实现
searchh
函数中的参数i
表示当前处理的行数。- 在
for
循环中,对于当前行的每一列,都尝试放置一个皇后。 - 在放置皇后时,通过检查数组 b,c,d来判断当前位置是否合法:
b[j]
表示第j
列是否已经有皇后;c[i+j]
表示主对角线是否已经有皇后;d[i-j+7]
表示副对角线是否已经有皇后。
- 如果当前位置合法,则标记相应列和对角线已经有皇后,并递归地处理下一行。
- 如果放置完八个皇后,即
i == 8
,则找到了一个解,计数器sum
自增。 - 在回溯时,需要将相应列和对角线的标记清除,以便重新尝试其他位置放置皇后。
3.3 源码&分析
c++
#include<iostream>
using namespace std;
int a[9];
int b[9]={0};
int c[16]={0};
int d[16]={0};
int sum=0;
void searchh(int i)
{
for(int j=1;j<=8;j++)
{
if((!b[j])&&(!c[i+j])&&(!d[i-j+7]))//每个皇后都有八个位置(列)可以试放
{
/********** Begin **********/
if (i == 8)
{
sum++;
return;
}
b[j] = 1;
c[i+j] = 1;
d[i-j+7] = 1;
searchh(i+1);
b[j] = 0;
c[i+j] = 0;
d[i-j+7] = 0;
/********** End **********/
}
}
}
3.4 结果分析
该题默认解决的是八皇后问题,所以确定n=8,结果为92,是固定的。若要实现n皇后问题,则同步扩大数组的大小,同样将得到正确的答案。
3.5 实验难点
本实验比较难理解的地方有以下两点
①注释缺失,难摩题意
给出的代码没有注释,有种让人做完形填空的美感。但是好在题目不是很难,看几遍也可以理解数组的含义。但是如果有注释,就能更加方便理解。
②参数不明,难以测试
调用算法的main函数没有给出,所以i的含义就很难猜出来。这导致我还要通过尝试来获取i的意思,给理解增加了难度。如果能把main函数给出,或者至少告诉我i的含义,会更好。
3.6 实验总结
本次实验还是比较基础的,使用回溯法解决了一个八皇后问题。再次锻炼了我对于回溯法的掌握以及深度优先算法的掌握。