毕竟新手上路23333,有谬误还请指正。 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限制又会有很多情况无法找到,然后果断放弃,改用广度搜索。  如果要改善代码效率还可以用双向搜索,即从起始状态和最终状态同时搜索,找到相同状态,这样搜索时间会缩短一半。此外还可以用A*(启发式算法)会显得高端很多。

题目要求: 在一个3*3的棋盘上,随机放置1到8的数字棋子,剩下一个空位。数字可以移动到空位(编程时,空位可用0代替,且可以理解为是空位的上、下、左、右移动),经过若干次移动后,棋局到达指定目标状态。 数组表示棋局状态。用函数表示空格(0)的移动,使用函数具有前提条件,满足条件才可以使用。 用广度优先或深度优先搜索求解。还可以使用启发式求解,以提高搜索效率。 要求: ① 编程求解问题; ② 给出中间状态; ③ 给出解序列(函数调用序列)

  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <queue>
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <ctime>
  8. #include <cstdio>
  9. #include <sstream>
  10. #include <deque>
  11. #include <functional>
  12. #include <iterator>
  13. #include <list>
  14. #include <map>
  15. #include <memory>
  16. #include <stack>
  17. #include <set>
  18. #include <numeric>
  19. #include <utility>
  20. #include <cstring>
  21. #include <fstream>
  22.  
  23. using namespace std;
  24. int board[]; //初始状态,一维数组模拟二维
  25. int destboard[]; //目标状态
  26. int dx[] = {-, , , }; //数字0的移动偏移量
  27. int dy[] = {, , , -};
  28. map<int, bool> mark; //记录已搜索的状态
  29.  
  30. int lists(int i, int j)
  31. {
  32. return i* + j; //返回i, j二维数组的一维位置
  33. }
  34.  
  35. int judge() //运算前判断是否可以找到一种对于初末状态可行的变换
  36. {
  37. int first_d[],last_d[],i,j=,k,rank1=,rank2=;
  38. for(i=;i<=;i++) //初状态赋值给first_d[10]
  39. {
  40. while()
  41. {
  42. if(j==){j=;}
  43. if(j==){j=;}
  44. first_d[i]=destboard[j];
  45. j++;
  46. break;
  47. }
  48. }
  49. j=;i=;
  50. for(k=;k<=;k++) //最终状态赋值给last_d[10]
  51. {
  52. while()
  53. {
  54. last_d[k]=board[lists(i, j)];
  55. j++;
  56. if(j==){i++;j=;}
  57. break;
  58. }
  59. }
  60.  
  61. for(j=;j<=;j++) //计算初状态的奇偶性
  62. {
  63. for(i=;i<j;i++)
  64. {
  65. if(first_d[i]>first_d[j]&&first_d[i]!=&&first_d[j]!=){rank1++;}
  66. }
  67. }
  68.  
  69. for(j=;j<=;j++) //计算末状态的奇偶性
  70. {
  71. for(i=;i<j;i++)
  72. {
  73. if(last_d[i]>last_d[j]&&last_d[i]!=&&last_d[j]!=){rank2++;}
  74. }
  75. }
  76. int a1=rank1%,a2=rank2%;
  77. if(a1!=a2){return ;} //判断奇偶性是否相同,相同才可以从出状态变到末状态
  78. else{return ;}
  79. }
  80.  
  81. struct Stat //结构体三个参数
  82. {
  83. int step; // 步数
  84. int board[]; // 状态
  85. Stat(int *b, int s=)
  86. {
  87. memcpy(this->board, b, sizeof(int)*); //对状态的赋值操作
  88. step = s;
  89. }
  90. };
  91.  
  92. bool ok(int *b) // 判断是否到已经达目标状态
  93. {
  94. for(int i=; i<=; ++i)
  95. for(int j=; j<=; ++j)
  96. {
  97. if(b[lists(i, j)] != destboard[lists(i, j)])
  98. return false;
  99. }
  100. return true;
  101. }
  102.  
  103. int Bfs()
  104. {
  105. int judge_first=judge();
  106. ofstream ofs; //建立数据外存文件
  107. ofs.open("output.dat");
  108. if(judge_first==){cout<<"不存在"<<endl;return ;}
  109. if(judge_first==)
  110. {
  111. queue<Stat> que; //建队que
  112. que.push(Stat(board, )); // 初始状态入队
  113. while(que.size())
  114. {
  115. int m=, mk=; // 记录状态m,以及基数mk
  116. Stat p = que.front(); //取出队头元素
  117. for(int i=; i<=; ++i)
  118. {
  119. for(int j=; j<=; ++j)
  120. {
  121. ofs<<p.board[lists(i, j)]<<" ";
  122. }
  123. ofs<<endl;
  124. }
  125. ofs<<endl;
  126.  
  127. que.pop(); //出队
  128.  
  129. if(ok(p.board))
  130. {
  131. return p.step; // 到达目标则返回最短步数
  132. }
  133.  
  134. for(int i=; i<=; ++i) // 这个是为了标记初始状态,不能遗漏
  135. for(int j=; j<=; ++j)
  136. {
  137. m+=p.board[lists(i, j)]*mk;
  138. mk*=;
  139. }
  140. if(!mark.count(m)) // 未标记则标记
  141. mark[m] = true;
  142.  
  143. for(int k=; k<; ++k) // 四个方向搜索
  144. {
  145. Stat n(p.board, p.step+); // n是下一步搜索的状态
  146. int zx, zy; // zx,zy存放当前状态0的位置
  147.  
  148. for(int i=; i<=; ++i) // 搜索当前状态的0的位置
  149. for(int j=; j<=; ++j)
  150. {
  151. if(p.board[lists(i,j)]==)
  152. {
  153. zx = i;
  154. zy = j;
  155. break;
  156. }
  157. if(p.board[lists(i,j)]==)
  158. break;
  159. }
  160.  
  161. int nx = zx+dx[k]; //下一个状态的0的位置
  162. int ny = zy+dy[k];
  163. m = ; //标记状态
  164. mk = ;
  165. swap(n.board[lists(nx,ny)],n.board[lists(zx, zy)]); //交换
  166.  
  167. for(int i=; i<=; ++i)
  168. for(int j=; j<=; ++j)
  169. {
  170. m+=n.board[lists(i, j)]*mk;
  171. mk*=;
  172. }
  173. if(!mark.count(m))
  174. {
  175. mark[m] = true;
  176. que.push(n); //若未搜索过,则入队
  177. }
  178. }
  179. }
  180. ofs.close(); //结束外存
  181. return ;
  182. }
  183. return ;
  184. }
  185.  
  186. int main()
  187. {
  188. cout<<"广度搜索八数码问题:\n";
  189. cout<<"请输入初始状态用0-8表示\n";
  190. memset(board, , sizeof(board));
  191. for(int i=; i<=; ++i)
  192. for(int j=; j<=; ++j)
  193. scanf("%1d", &board[lists(i, j)]);
  194.  
  195. cout<<"请输入结束状态\n";
  196. for(int m=;m<=;m++){scanf("%d",&destboard[m]);}
  197. for(int m=;m<=;m++){scanf("%d",&destboard[m]);}
  198. for(int m=;m<=;m++){scanf("%d",&destboard[m]);}
  199. mark.clear();
  200.  
  201. cout<<"准备搜索...\n";
  202. system("pause");
  203. cout<<"搜索中.....\n";
  204.  
  205. int t=Bfs();
  206. cout<<"搜索完毕,过程已经以文件的形式存储\n";
  207. if(t==){cout<<"没有找到"<<endl;}
  208. else{cout<<"深度为:"<<t<< endl;}
  209. system("pause");
  210. return ;
  211. }

输入初始状态和最终状态,中间过程会生成在”output.dat”中。

八数码问题:C++广度搜索实现的更多相关文章

  1. HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)

    题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原 ...

  2. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  3. [luogu]P1379 八数码难题[广度优先搜索]

    八数码难题 ——!x^n+y^n=z^n 我在此只说明此题的一种用BFS的方法,因为本人也是初学,勉勉强强写了一个单向的BFS,据说最快的是IDA*(然而蒟蒻我不会…) 各位如果想用IDA*的可以看看 ...

  4. codevs1225八数码难题(搜索·)

    1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description Yours和zero在研究A*启 ...

  5. Poj 1077 eight(BFS+全序列Hash解八数码问题)

    一.题意 经典的八数码问题,有人说不做此题人生不完整,哈哈.给出一个含数字1~8和字母x的3 * 3矩阵,如: 1  2  X            3 4  6            7  5  8 ...

  6. A*算法 -- 八数码问题和传教士过河问题的代码实现

    前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...

  7. ACM/ICPC 之 BFS-广搜进阶-八数码(经典)(POJ1077+HDU1043)

    八数码问题也称为九宫问题.(本想查查历史,结果发现居然没有词条= =,所谓的历史也就不了了之了) 在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个 ...

  8. BFS(八数码) POJ 1077 || HDOJ 1043 Eight

    题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...

  9. 双向广搜+hash+康托展开 codevs 1225 八数码难题

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

随机推荐

  1. pyinstaller 官方介绍

    http://www.pyinstaller.org/ pyinstaller支持多个平台,windows,linux,mac,兼容多个第三方包,包括pyqt,django,matplotlib Py ...

  2. win7下exe提示无法正常启动(0xc0000906)

    本人遇见是 avast问题,卸了

  3. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 这一篇文章我们主要来探讨一下Web Api的安全性,到目前为止所有的请求都是走的Http协议 ...

  4. 几个有用的jQuery代码片段

    1.检测Internet Explorer版本 $(document).ready(function() { if (navigator.userAgent.match(/msie/i) ){ ale ...

  5. ecshop if标签,超过N条,就输出记录 elseif、库存显示方式

    <!--商品详情右侧 相关商品推荐--> <!-- {if $related_goods} --> <!--{foreach from=$related_goods it ...

  6. mysql之用户授权

    授权命令: 1.全部权限:grant all on *.* to user@192.168.10.2 identified by "pass": 2.部分权限:grant sele ...

  7. OWIN support for the Web API 2 and MVC 5 integrations in Autofac

    Currently, in the both the Web API and MVC frameworks, dependency injection support does not come in ...

  8. Python操作Redis、Memcache、RabbitMQ、SQLAlchemy

    Python操作 Redis.Memcache.RabbitMQ.SQLAlchemy redis介绍:redis是一个开源的,先进的KEY-VALUE存储,它通常被称为数据结构服务器,因为键可以包含 ...

  9. Entity Framework - Using Transactions or SaveChanges(false) and AcceptAllChanges()?

    LINK With the Entity Framework most of the time SaveChanges() is sufficient. This creates a transact ...

  10. Yii2 事务

    $transaction = $connection->beginTransaction(); try { // ... executing other SQL statements ... $ ...