九宫格的启发式搜索
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
九宫格的启发式搜索
班级:计算机一班
姓名:覃荣锦
学号:*******
目录
一、实验目的 (3)
二、实验语言环境 (3)
三、实现设计 (3)
1.状态表示: (3)
2.算法介绍: (3)
1)广度优先搜索: (3)
2)深度优先搜索: (4)
3.初始化节点以及判断目标节点 (5)
4.拓展节点 (6)
5.搜索算法 (7)
四、程序全部代码 (8)
五、分析总结 (15)
1.数据结构分析 (15)
2.拓展方法分析 (15)
3.搜索算法分析 (15)
六、运行结果 (16)
七、遇见的问题以及解决方法 (16)
一、实验目的
加深对局部择优搜索以及全局择优搜索的熟悉程度。
了解局部择优搜索以及全局择优搜索的区别。
二、实验语言环境
系统:微软Window7系统
开发工具:visual c/c++ 6.0
语言:c语言
三、实现设计
1.状态表示:
九宫格状态以一组一维数组表示。1~8分别表示8个对应的数字,0表示空格,数据结构如下:
Typedef struct
{
Int data[9];
}Data;
九宫格节点为以线性表表示的树的节点,因此需要加入指向该节点父母的指针,在这里用下标表示,同时由于不同节点有不同的估值,因此需要加入表示其值变量。完整的数据结构如下:
typedef struct
{
int data[9];
int parent;
int value;
} Data;
2.算法介绍:
1)局部择优搜索:
第一步:把初始节点S0放入open表。
第二步:如果open表为空,则问题无解,退出。
第三步:把OPEN表的第一个节点取出放入CLOSE表,记该节点为节点n。
第四步:观察节点n是否为目标节点,若是,则求得问题的解,退出。
第五步:拓展节点n,将扩展的的节点排序后放入open表,将合法节点放入open表中。然后转到第二步。
2)全局择优搜索:
第一步:把初始节点S0放入open表。
第二步:如果open表为空,则问题无解,退出。
第三步:把OPEN表的最后一个节点取出放入CLOSE表,记该节点为节点n。
第四步:观察节点n是否为目标节点,若是,则求得问题的解,退出。
第五步:拓展节点n,将合法节点放入open表中。排序OPEN表。然后转到第二步。
3.辅助矩阵介绍
在本程序中,为了执行提高效率,在拓展和局面评估这两部分采用了矩阵作为辅助。
拓展辅助矩阵如下:
const static int check[9][4]=
{
{1,3,9,9},{0,2,4,9},{1,5,9,9},
{0,4,6,9},{1,3,5,7},{2,4,8,9},
{3,7,9,9},{4,6,8,9},{5,7,9,9}
};
在九宫格中,第0块可以和1、3块交换,第1块可以和0、2、4块交换……根据这个特点,本程序中生成如上的矩阵,对于第i块,它的可交换块为check[i][0]、check[i][1]、check[i][2]等等。
评估辅助矩阵如下:
const static int a[9][9]=
{
0,1,2,1,2,3,2,3,4,//1
1,0,1,2,1,2,3,2,3,//2
2,1,0,3,2,1,4,3,2,//3
1,2,3,0,1,2,1,2,3,//4
2,1,2,1,0,1,2,1,2,//5
3,2,1,2,1,0,3,2,1,//6
2,3,4,1,2,3,0,1,2,//7
3,2,3,2,1,2,1,0,1,//8
4,3,2,3,2,1,2,1,0,//9
};
该矩阵是一个二维矩阵,矩阵的值a[i][j]表示九宫格第i块和第j块的距离。
这可以很方便地求出第i块移动到目标点的代价。
比如,数字为n的块当前位置为p,则我们可以通过取a[n][p]的值直接求得它移动到目标花费的代价。当然,值为0的块目标位置是9,因此我们为它取值应该为a[9][p]。
4.初始化节点以及判断目标节点
由于硬件的局限性,我们不能保证任何局面都能在一遍内找到走法,因此我们在本程序中添加自动生成在当前硬件条件下可破解的局面。思路为从目标局面开始随机移动30~40步生成一个初始局面。并将该初始局面作为初始节点。
算法如下:
void InitData(int data[9])//随机生成可破解局面
{
srand((unsigned)time(NULL));//
int a[9]={1,2,3,4,5,6,7,8,0};
int k=rand()%10+30;
int j,l,temp;
while(k>=0)
{
for(l=0;l<9;l++)
if(a[l]==0) break;
j=rand()%4;
k--;
if(check[l][j]!=9)
{
temp=a[check[l][j]];
a[check[l][j]]=a[l];
a[l]=temp;
}
}
for(j=0;j<9;j++)
data[j]=a[j];
}
void Init(int data[9])
{
for(int i=0;i<9;i++)
open[opentop].data[i]=data[i];
open[opentop].parent=-1;
open[opentop].value=GetValue(open[opentop].data);
opentop++;
}
判断目标节点算法如下:
bool Checkwin(int data[9])
{
for(int i=0;i<8;i++)
if(data[i]!=i+1) return 0;
return 1;
}