Description

如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

Input

输入第一行包含九宫的初态,第二行包含九宫的终态。

Output

输出最少的步数,如果不存在方案,则输出-1。

Sample Input

  1. 样例输入1
  2. 12345678.
  3. 123.46758
  4.  
  5. 样例输入2
  6. 13524678.
  7. 46758123.

Sample Output

  1. 样例输出1
  2. 3
  3.  
  4. 样例输出2
  5. 22

Source

蓝桥杯
 
分析:暴力bfs会超时
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. #define INF 99999999
  5. #define me(a,x) memset(a,x,sizeof(a))
  6. int mon1[]= {,,,,,,,,,,,,};
  7. int mon2[]= {,,,,,,,,,,,,};
  8. int dir[][]= {{,},{,-},{,},{-,}};
  9. int fac[] = {, , , , , , , , , };//i的阶乘
  10.  
  11. LL getval()
  12. {
  13. LL ret();
  14. char c;
  15. while((c=getchar())==' '||c=='\n'||c=='\r');
  16. ret=c-'';
  17. while((c=getchar())!=' '&&c!='\n'&&c!='\r')
  18. ret=ret*+c-'';
  19. return ret;
  20. }
  21. void out(int a)
  22. {
  23. if(a>)
  24. out(a/);
  25. putchar(a%+'');
  26. }
  27. int kt(int a[],int n)//康托展开
  28. {
  29. int ans=;
  30. for(int i=;i<=n;i++)
  31. {
  32. int c=;
  33. for(int j=i+;j<=n;j++)
  34. {
  35. if(a[j]<a[i])
  36. c++;
  37. }
  38. ans+=(c*fac[n-i]);
  39. }
  40. return ans+;
  41. }
  42.  
  43. char str1[],str2[];
  44. int a[][],b[][];
  45. int sx,sy;
  46. int t[];
  47. int h;
  48. int w;
  49. bool vis[];
  50.  
  51. struct node
  52. {
  53. int x,y,step;//x,y代表空格位置
  54. int c[][];//九宫格数组
  55. node(int xx,int yy,int ss,int cc[][])//初始化
  56. {
  57. x=xx;
  58. y=yy;
  59. step=ss;
  60. for(int i=; i<=; i++)
  61. for(int j=; j<=; j++)
  62. c[i][j]=cc[i][j];
  63. }
  64. int getkt()//得到结点数组的康托展开值
  65. {
  66. h=;
  67. for(int i=;i<=;i++)
  68. {
  69. for(int j=;j<=;j++)
  70. {
  71. t[h++]=c[i][j];
  72. }
  73. }
  74. return kt(t,);
  75. }
  76. };
  77.  
  78. void init()//初始化
  79. {
  80. int cnt=;
  81. for(int i=; i<=; i++)//得到原始九宫格
  82. {
  83. for(int j=; j<=; j++)
  84. {
  85. if(str1[cnt]=='.')
  86. a[i][j]=,sx=i,sy=j;
  87. else
  88. a[i][j]=str1[cnt]-'';
  89. cnt++;
  90. }
  91. }
  92. cnt=;
  93. for(int i=; i<=; i++)//得到目标九宫格
  94. {
  95. for(int j=; j<=; j++)
  96. {
  97. if(str2[cnt]=='.')
  98. b[i][j]=;
  99. else
  100. b[i][j]=str2[cnt]-'';
  101. cnt++;
  102. }
  103. }
  104. me(vis,false);//九宫格状态数组
  105. h=;
  106. for(int i=;i<=;i++)//得到目标九宫格的康托展开值
  107. {
  108. for(int j=;j<=;j++)
  109. {
  110. t[h++]=b[i][j];
  111. }
  112. }
  113. w=kt(t,);
  114. }
  115. int check(int x,int y)//边界约束
  116. {
  117. if(x<=&&x>=&&y<=&&y>=)
  118. return ;
  119. return ;
  120. }
  121. int bfs(int x,int y,int a[][])
  122. {
  123. queue<node> q;
  124.  
  125. q.push(node(x,y,,a));
  126. vis[node(x,y,,a).getkt()]=;
  127.  
  128. while(!q.empty())
  129. {
  130. int x=q.front().x;
  131. int y=q.front().y;
  132. int step=q.front().step;
  133. int c[][];
  134. for(int i=; i<=; i++)
  135. for(int j=; j<=; j++)
  136. c[i][j]=q.front().c[i][j];
  137. q.pop();
  138.  
  139. for(int i=; i<; i++)
  140. {
  141. int xx=x+dir[i][];
  142. int yy=y+dir[i][];
  143. int ss=step+;
  144.  
  145. int cc[][];
  146. if(check(xx,yy)==)//越界
  147. continue;
  148.  
  149. for(int i=; i<=; i++)
  150. for(int j=; j<=; j++)
  151. cc[i][j]=c[i][j];
  152. cc[x][y]=cc[xx][yy];//移动
  153. cc[xx][yy]=;
  154.  
  155. if(vis[node(xx,yy,ss,cc).getkt()]==)//判断该状态的九宫格有没有搜索过
  156. {
  157. if(node(xx,yy,ss,cc).getkt()==w)//搜索到了目标
  158. {
  159. return ss;//返回步数
  160. }
  161. int temp=node(xx,yy,ss,cc).getkt();
  162.  
  163. vis[temp]=;//标记该状态的九宫格已经搜索过
  164. q.push(node(xx,yy,ss,cc));
  165. }
  166.  
  167. }
  168. }
  169. return -;
  170. }
  171. int main()
  172. {
  173. while(~scanf("%s",str1))
  174. {
  175. scanf("%s",str2);
  176. init();
  177.  
  178. int ans=bfs(sx,sy,a);
  179. printf("%d\n",ans);
  180. }
  181. }

蓝桥杯 历届试题 九宫重排 (bfs+康托展开去重优化)的更多相关文章

  1. Java实现 蓝桥杯 历届试题 九宫重排

    问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...

  2. 算法笔记_183:历届试题 九宫重排(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成 ...

  3. 蓝桥杯OJ PREV-19 九宫重排

    题目描写叙述:   历届试题 九宫重排   时间限制:1.0s   内存限制:256.0MB        问题描写叙述 如以下第一个图的九宫格中,放着 1~8 的数字卡片.另一个格子空着.与空格子相 ...

  4. 蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索

    问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走 ...

  5. 2013年第四届蓝桥杯国赛 九宫重排(HashMap+双BFS优化)

    九宫重排     时间限制:1.0s   内存限制:256.0MB 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干 ...

  6. 蓝桥杯 历届试题 剪格子(dfs搜索)

    历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |* || +--****--+ ||* | ** ...

  7. 蓝桥杯 历届试题 网络寻路(dfs搜索合法路径计数)

    X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径 ...

  8. 蓝桥杯 历届试题 约数倍数选卡片 (经典数论+DFS)

    闲暇时,福尔摩斯和华生玩一个游戏: 在N张卡片上写有N个整数.两人轮流拿走一张卡片.要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数.例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可 ...

  9. 蓝桥杯  历届试题 幸运数  dfs

    历届试题 幸运数 时间限制:1.0s   内存限制:256.0MB 问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的"筛法"生成 . 首先从1开始写出自然数1,2, ...

随机推荐

  1. HDU1698(KB7-E 线段树)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. HDU1069(KB12-C)

    Monkey and Banana Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. Stylus基本使用

    介绍 在学习一个 Vue.js 项目的过程中,注意到源码中样式的部分并没有用熟悉的 .css 样式文件,而是发现了代码长得和 CSS 相像的 .styl 文件.这个 .styl 以前没见过啊,你是谁? ...

  4. eclipse java web项目经常自动调试进入debug模式

    今天在运行Javaweb项目时,程序运行运行着就自动调试进入ThreadpoolExecutor,看着非常影响心情.最后在网上搜解决方法最后找到原因,解决方法如下. Window——>Prefe ...

  5. svn本地连接服务器失败,但是浏览器可以

    tortoise svn无法连接到服务器,清空“Autherticate data”后,再进行更新,提交,log查看等操作,svn还是不提示输入用户名和密码,而是报: error: Unable to ...

  6. HTTP协议学习随笔

    一 HTTP概述 HTTP简单说其实就是一套语言交流规则!Http使用的是可靠的数据传输协议,因此即使数据来自地球的另一端,也能够确保数据在传输过程中不会被损坏或产生混乱. B/S结构 用户在浏览器, ...

  7. Mac下使用VScode进行C/C++开发

    1.安装 从VScode官网下载Mac系统适用的VScode安装包,下载完成后,将zip安装包解压到桌面即可. 2.插件安装 实现 C/Cpp 代码自动补全,函数跳转. 打开VScode后,按下组合键 ...

  8. maven学习笔记--maven项目创建

    使用Maven命令和Eclipse的Maven插件,创建Maven项目 (1)maven命令生成项目         新建一个文件目录,dos进入该目录并执行下面命令: mvn archetype:c ...

  9. MySQL 性能监控4大指标——第一部分

    [编者按]本文作者为 John Matson,主要介绍 mysql 性能监控应该关注的4大指标. 第一部分将详细介绍前两个指标: 查询吞吐量与查询执行性能.文章系国内 ITOM 管理平台 OneAPM ...

  10. MySQL出现Waiting for table metadata lock的场景浅析

    MySQL版本为5.6.12. 在进行alter table操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的 ...