当前位置:   article > 正文

八数码难题(启发式搜索)_、应用启发式搜索算法求解课本八数码问题: 设评价函数 f(n) = d(n) + p(n)(错位棋

、应用启发式搜索算法求解课本八数码问题: 设评价函数 f(n) = d(n) + p(n)(错位棋

八数码难题---启发式搜素

 

1.启发式搜索:

特点:重排OPEN表,选择最有希望的节点加以扩展

种类:有序搜索(A算法)、A*算法等

 

2.估价函数

用来估算节点处于最佳求解路径上的希望程度的函数

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

 n——搜索图中的某个当前被扩展的节点;

f(n) ——从初始状态节点s, 经由节点n到达目标节点ng,估计的最小路径代价;

g(n) ——从s到n 的实际路径代价;

h(n)——从n到ng,估计的最小路径代价。

 八数码难题估价函数:f(n)=d(n)+w(n)                     

其中:d(n)为n的深度           w(n)为不在位的棋子数

 

3.有序搜索:

选择OPEN表上具有最小f值的节点作为下一个要扩展的节点。

八数码难题使用全局择优搜索:

   选择OPEN表上具有最小f值的节点作为下一个要扩展的节点,即总是选择最有希望的节点作为下一个要扩展的节点。

在八数码难题中, 令估价函数

       f(n)=d(n)+p(n)

启发函数h(n)=p(n),p(n)为不在位的棋子与其目标位置的距离之和,则有p(n)≤h*(n),满足A*算法的限制条件。

w(n)——不在位的棋子数,不够贴切,错误选用节点加以扩展。

p(n)——更接近于h*(n)的h(n),其值是节点n与目标状态节点相比较,每个错位棋子在假设不受阻拦的情况下,移动到目标状态相应位置所需走步的总和。

p(n)比w(n)更接近于h*(n),因为p(n)不仅考虑了错位因素,还考虑了错位的距离(移动次数)


数据结构的建立:由于open,close表常设计删除增加节点的操作,故使用单链表最好

open表存储生成的节点且未被处理的节点,处理过的节点取出放入close表

close表存储处理过的节点

status表存储所有生成的节点

采用全局择优的思想

 

java代码如下:
  1. package 八数码难题;
  2. import java.util.Collections;
  3. import java.util.LinkedList;
  4. import java.util.List;
  5. public class Main {
  6. static int f[][]=new int[3][3];
  7. static int e[][]=new int[3][3];
  8. static int p=0;
  9. static int dir[][]={{0,1},{1,0},{0,-1},{-1,0}};
  10. static List<node>openlist=new LinkedList<node>();
  11. static List<node>closelist=new LinkedList<node>();
  12. static int d=0;
  13. static List<node>status=new LinkedList<node>();
  14. public static void main(String[] args) {
  15. // TODO Auto-generated method stub
  16. String str1;//初始状态
  17. String str2;//目标状态
  18. str1="2831647.5";//空格用.表示
  19. str2="1238.4765";
  20. for(int i=0;i<str1.length();i++){
  21. f[i/3][i-i/3*3]=str1.charAt(i)=='.'?0:str1.charAt(i)-'0';
  22. e[i/3][i-i/3*3]=str2.charAt(i)=='.'?0:str2.charAt(i)-'0';
  23. }
  24. node f1=new node(f,d,e);
  25. openlist.add(f1);
  26. status.add(f1);
  27. Search();//寻找最短路径
  28. toPrint();//输出状态空间
  29. }
  30. public static boolean check(int x,int y){
  31. if(x<0||x>=3||y<0||y>=3){
  32. return false;
  33. }
  34. return true;
  35. }
  36. public static boolean contains(List<node> list,int a[][]){
  37. int flag=0;
  38. int a1[][] = new int[3][3];
  39. for(int i=0;i<list.size();i++){
  40. flag=0;
  41. for(int j=0;j<3;j++){
  42. a1[j]=list.get(i).a[j].clone();
  43. for(int k=0;k<3;k++){
  44. if(a1[j][k]==a[j][k]){
  45. flag++;
  46. }
  47. }
  48. }
  49. if(flag==9) return false;
  50. }
  51. return true;
  52. }
  53. //输出状态空间
  54. public static void toPrint(){
  55. int a[][];
  56. System.out.println();
  57. System.out.println("========状态空间大小为:"+status.size()+"-----");
  58. int k1=0,i=0;
  59. while(i<status.size()){
  60. a=status.get(i).a;
  61. System.out.println("---------------");
  62. for(int j=0;j<3;j++){
  63. for(int k=0;k<3;k++){
  64. System.out.print(a[j][k]+" ");
  65. }
  66. System.out.println();
  67. }
  68. i++;
  69. }
  70. }
  71. public static void Search(){
  72. hnode ehn=new hnode(e);
  73. while(!openlist.isEmpty()){
  74. int at[][]=new int[3][3];
  75. int min=0;
  76. for(int i=0;i<openlist.size();i++){
  77. if(openlist.get(i).f<openlist.get(min).f){
  78. min=i;
  79. }
  80. }
  81. node n=null;
  82. n=openlist.remove(min);
  83. closelist.add(n);
  84. for(int i=0;i<3;i++){
  85. at[i]=n.a[i].clone();
  86. }
  87. int x = 0,y = 0;
  88. for(int i=0;i<3;i++){
  89. for(int j=0;j<3;j++){
  90. if(at[i][j]==p){
  91. x=i;y=j;//记录空格在棋盘中的位置(原)
  92. break;
  93. }
  94. }
  95. }
  96. for(int i=0;i<4;i++){
  97. int nx,ny,t;
  98. nx=x+dir[i][0];//空格移动的位置(现)
  99. ny=y+dir[i][1];
  100. if(check(nx,ny)){
  101. t=at[nx][ny];
  102. at[nx][ny]=at[x][y];
  103. at[x][y]=t;
  104. d=n.h+1;
  105. hnode thn=new hnode(at);
  106. node tn=new node(at,d,e);
  107. if(thn.equals(ehn)){
  108. //找到最短路径
  109. status.add(tn);
  110. closelist.add(tn);
  111. toOutput();
  112. return;
  113. }
  114. if(contains(openlist,at)&&contains(closelist,at)){
  115. openlist.add(tn);
  116. status.add(tn);
  117. }
  118. t=at[nx][ny];
  119. at[nx][ny]=at[x][y];
  120. at[x][y]=t;
  121. }
  122. }
  123. }
  124. return;
  125. }
  126. public static void toOutput(){
  127. System.out.println("====移动路径如下====");
  128. System.out.println("所需步数为:"+d);
  129. for(int i=0;i<closelist.size();i++){
  130. int a[][]=closelist.get(i).a;
  131. System.out.println("----------------------");
  132. for(int j=0;j<3;j++){
  133. for(int k=0;k<3;k++){
  134. System.out.print(a[j][k]+" ");
  135. }
  136. System.out.println();
  137. }
  138. }
  139. }
  140. }
  141. class hnode{
  142. //hash用于hashSet
  143. int hash;
  144. public hnode(){
  145. }
  146. public hnode(int a[][]){
  147. int hc=0;
  148. for(int i=0;i<3;i++){
  149. for(int j=0;j<3;j++){
  150. hc*=10;
  151. hc+=a[i][j];
  152. }
  153. }
  154. this.hash=hc;
  155. }
  156. public boolean equals(Object object){
  157. hnode thn=(hnode)object;
  158. return thn.hash==hash;
  159. }
  160. @Override
  161. public int hashCode(){
  162. return hash;
  163. }
  164. }
  165. class node{
  166. int a[][];//九宫格的状态
  167. int h;//深度
  168. int f;//从初始状态节点s, 经由节点n到达目标节点ng,估计的最小路径代价
  169. int p;//不在位的棋子与其目标位置的距离之和
  170. public node(int [][]a,int h,int [][]e){
  171. this.a=new int[3][];
  172. for(int i=0;i<3;i++){
  173. this.a[i]=a[i].clone();
  174. }
  175. this.h=h;
  176. this.p=work(e);
  177. this.f=this.h+this.p;
  178. }
  179. public int work(int e[][]){
  180. int ants=0;
  181. for(int i=0;i<3;i++){
  182. for(int j=0;j<3;j++){
  183. if(a[i][j]!=e[i][j]&&a[i][j]!=0){
  184. int r=0,c = 0,flag=0;
  185. for(int k=0;k<3;k++){
  186. for(int k1=0;k1<3;k1++){
  187. if(a[i][j]==e[k][k1]){
  188. r=k;
  189. c=k1;
  190. ants+=Math.abs(r-i);
  191. ants+=Math.abs(c-j);
  192. flag=1;
  193. break;
  194. }
  195. }
  196. if(flag==1) break;
  197. }
  198. }
  199. }
  200. }
  201. return ants;
  202. }
  203. }

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

闽ICP备14008679号