八数码难题

——!x^n+y^n=z^n

  我在此只说明此题的一种用BFS的方法,因为本人也是初学,勉勉强强写了一个单向的BFS,据说最快的是IDA*(然而蒟蒻我不会…)

  各位如果想用IDA*的可以看看这位大佬的这篇文章:

http://www.cnblogs.com/ZYBGMZL/p/6852733.html

  接下来是我的方法,用luogu的跑了最慢是200ms,感觉还行把。

题目描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入输出格式

输入格式:

输入初试状态,一行九个数字,空格用0表示

输出格式:

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

输入输出样例

输入样例#1

283104765

输出样例#1

4

  因为这是要最优解且保证数据有解,于是就想到了BFS。

  然而这个过程是有许多障碍的,要怎样检验自己的状态是否为解,还有判重的操作,如果你没有判重,TLE即在眼前…

所以我们可以想到压缩状态!当然如果用二进制难免有点力不从心,那我们干脆存成整数不就行了?但是可能你会发现,会有前导零的情况,怎么办?

这时候其实可以在状态前加一个1,在int型中还是过得去的。

  那判重怎么搞?注意到这只有9!种状态。

  想到什么?康托尔展开!对于0~8的全排列,

  012345678 的字典序是1,如果让你手动操作我想没什么问题,那怎么让计算机做这件事?

  对于 (a(n-1) a(n-2)L a(0))的字典序计算方法为:

  Σ(ci*i!)ci为当前未出现的比ai小的数的个数。

  既然这样,我们就能把状态一一存下来了,交换的话很简单,读者手动操作即可发现规律。

  简单说明之后附上代码参考一下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. #define maxn 400000
  6. //阶乘?我当然打表啦。
  7. ]={,,,,,,,,,};
  8. //状态
  9. struct sjs{
  10. int num;
  11. int pos;
  12. }state[maxn];
  13. //队列
  14. struct _757{
  15. int time;
  16. int now;
  17. int fd;
  18. }qu[maxn];
  19. ];
  20. //判重
  21. bool rep[maxn];
  22. int head,tail;
  23. //特殊嗜好???
  24. namespace lys{
  25. //快速幂
  26. int fpow(int p){
  27. ,;
  28. ){
  29. ) res*=base;
  30. base*=base;
  31. p>>=;
  32. }
  33. return res;
  34. }
  35. //计算cantor
  36. int cantor(int num){
  37. ,pos,res=;
  38. int x=num;
  39. memset(cto,,sizeof cto);
  40. ){
  41. cto[i]=num%;
  42. ) pos=i;
  43. num/=;
  44. i++;
  45. }
  46. int j,cal;
  47. ;i>=;i--){
  48. cal=;
  49. ;j>i;j--){
  50. if(cto[j]<cto[i]) cal++;
  51. }
  52. res+=(cto[i]-cal)*fac[i];
  53. }
  54. state[res+].num=x;
  55. state[res+].pos=pos;
  56. ;
  57. }
  58. //判断是否能移动
  59. bool chk(int pos,int i){
  60. switch(i){
  61. :) return true ; return false ;
  62. :) return true ; return false ;
  63. :||pos==||pos==) return false ; return true ;
  64. :||pos==||pos==) return false ; return true ;
  65. }
  66. }
  67. int bfs(){
  68. ,i,st,ch,fp,x,num;
  69. do{
  70. st=qu[head].now;
  71. fp=fpow(state[st].pos);
  72. num=state[st].num;
  73. ;i<=;i++){
  74. if(chk(state[st].pos,i)){
  75. switch(i){
  76. :
  77. x=(num/(fp*))%;
  78. ch=num-x*fp*+x*fp;
  79. x=cantor(ch);
  80. qu[++tail].now=x;
  81. qu[tail].time=(qu[head].time+);
  82. qu[tail].fd=head;
  83. //目标态,觉得不这样写也行,直接用num比较
  84. ){
  85. return qu[tail].time;
  86. }
  87. if(rep[x]) tail--;
  88. else rep[x]=true ;
  89. break ;
  90. :
  91. x=(num/(fp/))%;
  92. ch=num-x*fp/+x*fp;
  93. x=cantor(ch);
  94. qu[++tail].now=x;
  95. qu[tail].time=(qu[head].time+);
  96. qu[tail].fd=head;
  97. ){
  98. return qu[tail].time;
  99. }
  100. if(rep[x]) tail--;
  101. else rep[x]=true ;
  102. break ;
  103. :
  104. x=(num/(fp*))%;
  105. ch=num+x*fp-x*fp*;
  106. x=cantor(ch);
  107. qu[++tail].now=x;
  108. qu[tail].time=(qu[head].time+);
  109. qu[tail].fd=head;
  110. ){
  111. return qu[tail].time;
  112. }
  113. if(rep[x]) tail--;
  114. else rep[x]=true ;
  115. break ;
  116. :
  117. x=(num/(fp/))%;
  118. ch=num+x*fp-x*fp/;
  119. x=cantor(ch);
  120. qu[++tail].now=x;
  121. qu[tail].time=(qu[head].time+);
  122. qu[tail].fd=head;
  123. ){
  124. return qu[tail].time;
  125. }
  126. if(rep[x]) tail--;
  127. else rep[x]=true ;
  128. break ;
  129. }
  130. }
  131. }
  132. head++;
  133. }while(head<=tail);
  134. }
  135. int main(){
  136. int i,j;
  137. char c;
  138. ;
  139. ;i<=;i++){
  140. ;j<=;j++){
  141. c=getchar();
  142. ') c=getchar();
  143. st=st*+c-';
  144. }
  145. }
  146. //初始状态
  147. +st);
  148. qu[++head].now=r;
  149. qu[head].time=;
  150. rep[r]=true ;
  151. tail=;
  152. printf("%d\n",bfs());
  153. ;
  154. }
  155. }
  156. int main(){
  157. lys::main();
  158. ;
  159. }

[luogu]P1379 八数码难题[广度优先搜索]的更多相关文章

  1. luogu P1379 八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...

  2. luogu P1379 八数码难题(A*算法入门详细讲解)

     代码实现细节 #include<cstdio> #include<cstring> #include<iostream> using namespace std; ...

  3. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  4. 洛谷——P1379 八数码难题

    P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...

  5. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

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

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

  7. 洛谷—— P1379 八数码难题

    https://daniu.luogu.org/problem/show?pid=1379 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示 ...

  8. 洛谷 P1379 八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...

  9. 洛谷 - P1379 - 八数码难题 - bfs

    https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...

随机推荐

  1. Centos 环境一键部署脚本(shell脚本)

    谨以此文纪念吊炸天的Centos环境一键部署方案的新鲜出炉 辛苦大半年,产品准备上线了,BOSS亲自体验安装部署,看着超过200+页的安装文档直接崩溃了(需要部署23个基础服务),经历了超过3个小时的 ...

  2. Hadoop的编译

    Hadoop2.4.0  重新编译 64  位本地库 原创作者:大鹏鸟 时间:2014-07-28 环境:虚拟机 VirtualBox,操作系统 64 位 CentOS 6.4 下载重新编译需要的软件 ...

  3. [0] C#实现WebBrowser&HTML交互

    using System;using System.ComponentModel;using System.Windows.Forms; namespace WindowsApplication5{ ...

  4. scrapy代理的设置

    scrapy代理的设置 在我的上一篇文章介绍了scrapy下载器中间件的使用,这里的scrapyIP的代理就是用这个原理实现的,重写了下载器中间件的process_request(self,reque ...

  5. qt中setStyleSheet导致的内存泄漏

    原始日期: 2017-01-05 19:31 现象:程序运行至某一个界面下,内存出现缓慢持续的占用内存增长   原因:经过排查,确定是在事件派发的槽函数中频繁重复调用setStyleSheet导致的 ...

  6. Index Scans 索引扫描

    官方文档链接地址 http://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CNCPT1170 Index Scans 在索 ...

  7. 二维码生成api

    <img id='qrcode_img' src='http://qr.liantu.com/api.php?text={$wenzi}&w={$width}' /> http:/ ...

  8. 【Android Developers Training】 17. 停止和重启一个Activity

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 4.jsp的内置对象

    1.jsp有九大内置对象 out request response session application page pagecontext exception config 2.用户发请求 requ ...

  10. HTML5 进阶系列:文件上传下载

    前言 HTML5 中提供的文件API在前端中有着丰富的应用,上传.下载.读取内容等在日常的交互中很常见.而且在各个浏览器的兼容也比较好,包括移动端,除了 IE 只支持 IE10 以上的版本.想要更好地 ...