当前位置:   article > 正文

启发式算法解决八数码(九宫)问题_启发式解决八数码问题

启发式解决八数码问题

人工智能课程实验


  背景知识:


估价函数

在对问题的状态空间进行搜索时,为提高搜索效率需要和被解问题的解有关的大量控制性知识作为搜索的辅助性策略。这些控制信息反映在估价函数中。

估价函数的任务就是估计待搜索节点的重要程度,给这些节点排定次序。估价函数可以是任意一种函数,如有的定义它是节点x处于最佳路径的概率上,或是x节点和目标节点之间的距离等等。在此,我们把估价函数f(n)定义为从初始节点经过n节点到达目标节点的最小代价路径的代价估计值,它的一般形式是:

      f(n) = g(n) + h(n)

其中g(n)是从初始节点到节点n的实际代价,g(n)可以根据生成的搜索树实际计算出来;h(n)是从n到目标节点的最佳路径的代价估计,h(n)主要体现了搜索的启发信息。

1)  状态表示的数据结构

struct  Node

{

    stringfather;

    stringid;

    intf,g=0,h;

    intvalue[3][3];

};

value为3X3的九宫格,表示为当前状态,f,g,h分别对应估价函数中的f(n)= g(n) + h(n),id为当前状态的唯一表示,即九宫格数字的顺序排序,空格用‘0’来表示,则实例中的第一个状态的id即为‘283164705’,father为父状态的id。

2)  状态扩展规则的表示

从某一状态出发,寻找空格的位置,探寻空格的上下左右四个方向可移动性,并避免走回头路,计算下一节点的估价函数值。

int calcuH(int *value)

{

    int h=0;

    for(int i= 0; i < 9; i++)

    {

        intnum=value[i]-1;

       if(num==-1)continue;

        intnowx=i%3,nowy=i/3;

        intgoalx=num%3,goaly=num/3;

       h+=abs(nowx-goalx)+abs(nowy-goaly);   

    }

    returnh;}

估价函数为所有数字当前的位置和目标位置的水平距离和垂直距离的绝对值的和。

3)  搜索产生的状态空间图


4)  OPEN表和CLOSE表变化过程

从open表取出最后一个状态,进行状态搜索,将新搜索到的点加入open表,后将该状态加入close表,最后重新排序open表。

  1. #include "iostream"
  2. #include <vector>
  3. #include <algorithm>
  4. #include <stack>
  5. #include <sstream>
  6. #include <stdlib.h>
  7. using namespace std;
  8. struct Node
  9. {
  10. string father;
  11. string id;
  12. int f,g=0,h;
  13. int value[3][3];
  14. };
  15. string getID(int *value)
  16. {
  17. stringstream ss;
  18. for(int i = 0; i < 9; i++)
  19. {
  20. ss<<value[i];
  21. }
  22. return ss.str();
  23. }
  24. int calcuH(int *value)
  25. {
  26. int h=0;
  27. for(int i = 0; i < 9; i++)
  28. {
  29. int num=value[i]-1;
  30. if(num==-1)continue;
  31. int nowx=i%3,nowy=i/3;
  32. int goalx=num%3,goaly=num/3;
  33. h+=abs(nowx-goalx)+abs(nowy-goaly);
  34. }
  35. return h;
  36. }
  37. bool operator == (const Node & obj1,const Node & obj2)
  38. {
  39. return obj1.id== obj2.id;
  40. }
  41. bool cmpH (Node i,Node j) { return (i.h>j.h); }
  42. vector<Node> close;
  43. vector<Node> open;
  44. static int oldH=999999;
  45. Node bestResult;
  46. int moveMat[9][4]={
  47. {0,1,1,0},
  48. {0,1,1,1},
  49. {0,0,1,1},
  50. {1,1,1,0},
  51. {1,1,1,1},
  52. {1,0,1,1},
  53. {1,1,0,0},
  54. {1,1,0,1},
  55. {1,0,0,1}
  56. };//move mat ,list as up right down left
  57. void outPrint( Node result )
  58. {
  59. vector<Node>::iterator iter;
  60. stack<Node> outStack;
  61. outStack.push(result);
  62. int time=-1;
  63. while(result.father!="start")
  64. {
  65. result.id=result.father;
  66. iter = find(close.begin(), close.end(), result);
  67. if(iter != close.end())
  68. {
  69. result=*iter;
  70. outStack.push(result);
  71. }
  72. else
  73. {
  74. cout<<"program error in outprint"<<endl;
  75. break;
  76. }
  77. }
  78. Node oneRow[5];
  79. int p=0,changeRow=5;
  80. while(!outStack.empty())
  81. {
  82. oneRow[p++]=outStack.top();
  83. outStack.pop();
  84. time++;
  85. if(p==changeRow)
  86. {
  87. p=0;
  88. for(int row = 0; row < 3; row++)
  89. {
  90. for(int col = 0; col < changeRow; col++)
  91. {
  92. cout<< oneRow[col].value[row][0] <<oneRow[col].value[row][1]<<oneRow[col].value[row][2];
  93. if(row==1)
  94. cout<<" -> ";
  95. else
  96. cout<<" ";
  97. }
  98. cout<<endl;
  99. }
  100. cout<<"\n---------"<<time<<"----------"<<endl;
  101. }
  102. }
  103. for(int row = 0; row < 3; row++)
  104. {
  105. for(int col = 0; col < p; col++)
  106. {
  107. cout<< oneRow[col].value[row][0] <<oneRow[col].value[row][1]<<oneRow[col].value[row][2];
  108. if(row==1)
  109. cout<<" -> ";
  110. else
  111. cout<<" ";
  112. }
  113. cout<<endl;
  114. }
  115. cout<<"\n---------"<<time<<"----------"<<endl;
  116. cout<<"This result sum step: "<<time<<endl;
  117. oldH=999999;
  118. system("pause");
  119. }
  120. void finalOutPrint()
  121. {
  122. if(bestResult.father!="NO")
  123. {
  124. cout<<"----This is Finally best result"<<endl;
  125. outPrint(bestResult);
  126. cout<<"----This is Finally best result"<<endl;
  127. cout<<"Search all node finish"<<endl;
  128. }
  129. else
  130. cout<<"No result,is error"<<endl;
  131. }
  132. void move(Node node,int blockSite,int direction)
  133. {
  134. int moveSite,oldH=node.h,*pvalue=(int*)node.value;
  135. switch (direction)
  136. {
  137. case 0:
  138. moveSite=blockSite-3;
  139. break;
  140. case 1:
  141. moveSite=blockSite+1;
  142. break;
  143. case 2:
  144. moveSite=blockSite+3;
  145. break;
  146. case 3:
  147. moveSite=blockSite-1;
  148. break;
  149. default:
  150. cout<<"error!!"<<endl;
  151. exit(1);
  152. break;
  153. }
  154. {
  155. int temp;
  156. temp=pvalue[blockSite];
  157. pvalue[blockSite]=pvalue[moveSite];
  158. pvalue[moveSite]=temp;
  159. }
  160. node.father=node.id;
  161. node.id=getID((int*)node.value);
  162. node.g++;
  163. if(node.id=="123456780")
  164. {
  165. outPrint(node);
  166. if(node.g<bestResult.g)
  167. {
  168. bestResult.father=node.father;
  169. bestResult.g=node.g;
  170. }
  171. }
  172. else
  173. {
  174. node.h=calcuH((int*)node.value);
  175. node.f=node.g+node.h;
  176. vector<Node>::iterator iter;
  177. iter = find(close.begin(), close.end(), node);
  178. if(iter != close.end())
  179. {
  180. if(iter->g>node.g)
  181. {
  182. iter->father=node.father;
  183. iter->g=node.g;
  184. iter->f=node.f;
  185. }
  186. }
  187. else
  188. {
  189. iter = find(open.begin(), open.end(), node);
  190. if(iter != open.end())
  191. {
  192. if(iter->g>node.g)
  193. {
  194. iter->father=node.father;
  195. iter->g=node.g;
  196. iter->f=node.f;
  197. }
  198. }
  199. else //if not in close or open ,add new
  200. {
  201. open.push_back(node);
  202. }
  203. }
  204. }
  205. }
  206. int search()
  207. {
  208. int loop=0;
  209. int staytime=0;
  210. while(!open.empty())
  211. {
  212. sort(open.begin(),open.end(),cmpH);
  213. Node nowNode=open.back();
  214. int *pvalue=(int*)nowNode.value;
  215. {
  216. if(nowNode.h<oldH)
  217. {
  218. staytime=0;
  219. oldH=nowNode.h;
  220. }
  221. else
  222. {
  223. staytime++;
  224. }
  225. if(staytime==3000)
  226. {
  227. break;
  228. }
  229. }
  230. open.pop_back();
  231. close.push_back(nowNode);
  232. if(nowNode.id=="123456780")
  233. {
  234. outPrint(nowNode);
  235. continue;
  236. }
  237. int blockSite; //get empty situation
  238. for(int i = 0; i < 9; i++)
  239. {
  240. if(pvalue[i]==0)
  241. {
  242. blockSite=i;
  243. break;
  244. }
  245. }
  246. { //check direction
  247. if(moveMat[blockSite][0]==1)
  248. {
  249. move(nowNode,blockSite,0);
  250. }
  251. if(moveMat[blockSite][1]==1)
  252. {
  253. move(nowNode,blockSite,1);
  254. }
  255. if(moveMat[blockSite][2]==1)
  256. {
  257. move(nowNode,blockSite,2);
  258. }
  259. if(moveMat[blockSite][3]==1)
  260. {
  261. move(nowNode,blockSite,3);
  262. }
  263. }
  264. }
  265. finalOutPrint();
  266. return 0;
  267. }
  268. int main(int argc, char const *argv[])
  269. {
  270. Node head;
  271. head.father="start";
  272. bestResult.father="NO";
  273. bestResult.g=99999;
  274. int aim[]={1,2,3,4,5,6,7,8,0};\
  275. memcpy(bestResult.value,aim,9*sizeof(int));
  276. int start[]=
  277. {
  278. 4,1,2,
  279. 7,5,3,
  280. 0,8,6
  281. };
  282. int inversion=0;
  283. for(int i = 0; i < 9; i++)
  284. {
  285. if(start[i]!=0)
  286. for(int j = i+1; j < 9; j++)
  287. {
  288. if(start[j]!=0&&start[i]>start[j])
  289. {
  290. inversion++;
  291. }
  292. }
  293. }
  294. //cout<<inversion<<endl;
  295. if(inversion%2!=0)
  296. cout<<"this series is unsolvable"<<endl;
  297. else
  298. {
  299. memcpy(head.value,start,9*sizeof(int));
  300. head.id=getID((int*)head.value);
  301. head.h=calcuH((int*)head.value);
  302. open.push_back(head);
  303. search();
  304. }
  305. return 0;
  306. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/370833
推荐阅读
相关标签
  

闽ICP备14008679号