<题目链接>

题目大意:
给出一个3×3的矩阵(包含1~8数字和一个字母x),经过一些移动格子上的数后得到连续的1~8,最后一格是x,要求最小移动步数。

解题分析:
本题用BFS来寻找路径,为了降低复杂度,用BFS从最终的目标状态开始处理,将所有搜索到状态以及对应的路径打表记录,然后对于输入的矩阵,直接查表输出答案 即可,本题还有一个难点,就是如何判断记录已经搜索过的状态,如果使用map+string(矩阵看成一维)会超时,所以我们这里用康拓展开式来记录状态。这道题比较玄学的地方在于如果更换dir 中四个方向的顺序,可能会WA,而在题目中没有对输出的字符串做任何限制,不知道这是为什么。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<queue>
  4. using namespace std;
  5. typedef struct nn
  6. {
  7. char way; //记录操作
  8. int fath; //记录父节点,用于记录路径
  9. }node1;
  10.  
  11. typedef struct nod
  12. {
  13. int aa[];
  14. int n; //n为9在aa中的位置
  15. int son; //记录aa的康拓展开式
  16. }node2;
  17.  
  18. int dir[][]={{,},{,-},{,},{-,}},fac[];
  19. node1 Node[];//节点
  20.  
  21. void set_fac()//计算0到8的阶层
  22. {
  23. fac[]=;
  24. for(int i=;i<=;i++)
  25. fac[i]=fac[i-]*i;
  26. }
  27.  
  28. int cantor(int aa[])//康托展开,掌握康拓展开的方法
  29. {
  30. int ans=;
  31. for(int i=;i<;i++)
  32. {
  33. int k=;
  34. for(int j=i+;j<;j++)
  35. if(aa[i]>aa[j])
  36. k++;
  37. ans+=k*fac[-i]; //i点以后比aa[i]小的数的个数*((n-i)-1)! 之和
  38. }
  39. return ans;
  40. }
  41.  
  42. void bfs(int a[])
  43. {
  44. queue<node2>Q;
  45. node2 now,next;
  46.  
  47. for(int i=;i<;i++) now.aa[i]=a[i];
  48. now.n=;now.son=;
  49. Node[now.son].fath=; //把最终父节点记为0,也就是本身
  50. Q.push(now);
  51. while(!Q.empty())
  52. {
  53. now=Q.front(); Q.pop();
  54. for(int k=;k<;k++)
  55. {
  56. next=now;
  57. int tx=now.n/+dir[k][];
  58. int ty=now.n%+dir[k][];
  59. if(ty>=&&tx>=&&ty<&&tx<)
  60. {
  61. next.n=tx*+ty; //得到移动后x的位置
  62. int tem=next.aa[next.n]; //得到移动后该位置的原数字
  63. next.aa[next.n]=next.aa[now.n];
  64. next.aa[now.n]=tem; //将两个位置上的数字交换
  65. next.son=cantor(next.aa);
  66.  
  67. if(Node[next.son].fath==-) //为-1时表示这个点没有访问过,那么放入队列
  68. {
  69. Node[next.son].fath=now.son; //当前节点的父节点就是上一个节点
  70. if(k==)Node[next.son].way='l';//一定要注意了,k=0是向右走,但我们是从终止状态往回搜,所以直接记录相反的方向
  71. if(k==)Node[next.son].way='r';
  72. if(k==)Node[next.son].way='u';
  73. if(k==)Node[next.son].way='d';
  74. Q.push(next);
  75. }
  76. }
  77. }
  78. }
  79. }
  80.  
  81. int main()
  82. {
  83. int i,j,s,ss[],a[];
  84.  
  85. for(i=;i<;i++)//目标状态
  86. a[i]=i+; //建立目标一维矩阵,把x看成9
  87.  
  88. for(i=;i<;i++)
  89. Node[i].fath=-;
  90. set_fac(); //计算阶层
  91. bfs(a); //将从最终状态能够延伸出去的所有状态以及对应路径提前打表记录
  92.  
  93. char str[];
  94. while(gets(str))
  95. {
  96. for(i=,j=;str[i]!='\0';i++)//把字符串变成数子
  97. {
  98. if(str[i]=='x')
  99. ss[j++]=; //把x变为数子9
  100. else if(str[i]>=''&&str[i]<='')
  101. ss[j++]=str[i]-'';
  102. }
  103. s=cantor(ss); //算出初态康托值
  104. if(Node[s].fath==-) {printf("unsolvable\n");continue;} //不能变成目标,因为当从起点开始搜索的时候,fath表示搜索到某
  105. //点时,上一个点的状态,所以,如果s.fath==-1时,表示这个矩阵根本就延伸不出去,不可能达到目标状态
  106.  
  107. while(s!=)
  108. {
  109. printf("%c",Node[s].way);
  110. s=Node[s].fath;
  111. }
  112. printf("\n");
  113. }
  114. }

2018-09-06

hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】的更多相关文章

  1. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  2. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  3. Hdu 1043 Eight (八数码问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动 ...

  4. 【HDU - 1043】Eight(反向bfs+康托展开)

    Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的 ...

  5. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  6. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  7. HDU 4531 bfs/康拓展开

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4531 吉哥系列故事——乾坤大挪移 Time Limit: 2000/1000 MS (Java/Othe ...

  8. [cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)

    快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚 ...

  9. poj 1077-Eight(八数码+逆向bfs打表)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

随机推荐

  1. D3.js 添加zoom缩放功能后dblclick双击也会放大的问题

    svg.call(zoom).on("dblclick.zoom", null); https://stackoverflow.com/questions/25007466/d3- ...

  2. laravel Blade 模板引擎

    与视图文件紧密关联的就是模板代码,我们在视图文件中通过模板代码和 HTML 代码结合实现视图的渲染.和很多其他后端语言不同,PHP 本身就可以当做模板语言来使用,但是这种方式有很多缺点,比如安全上的隐 ...

  3. IP的计算

    IP的计算 时间限制: 1 Sec  内存限制: 32 MB 位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如192 ...

  4. 微信开发者工具_小程序js文件后面的M代表什么

    Git 版本管理为了方便开发者更简单快捷地进行代码版本管理,简化一些常用的 Git 操作,以及降低代码版本管理使用的学习成本,开发者工具集成了 Git 版本管理面板.A: 增加的文件.C: 文件的一个 ...

  5. 封装input 逐渐,且input插件必须带有默认值。

    封装input 逐渐,且input插件必须带有默认值. 组件: <template> <div class="input-show"> <span c ...

  6. JavaMail在Windows平台下正常发送邮件,部署到Linux后则发送失败

    问题: 在本机(Windows)环境下可以成功发送邮件,但部署到Linux服务器上后不能成功发送,前台不提示错误或提示502. linux下日志提示:javamail isssl false.... ...

  7. 008-Python-模块

    1.模块 1.1什么是模块 一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀: 模块分为: 内置模块(内部定义的如time,os,sys等) 第三方模块(需要安装 ...

  8. dubbo负载均衡策略和集群容错策略都有哪些

    dubbo负载均衡策略 random loadbalance 默认情况下,dubbo是random load balance随机调用实现负载均衡,可以对provider不同实例设置不同的权重,会按照权 ...

  9. TURN TAP: Temporal Unit Regression Network for Temporal Action Proposals(ICCV2017)

    Motivation 实现快速和准确地抽取出视频中的语义片段 Proposed Method -提出了TURN模型预测proposal并用temporal coordinate regression来 ...

  10. 1个汉字在UTF-8编码占3个字节

    http://blog.csdn.net/ns_code/article/details/14162087 http://www.ruanyifeng.com/blog/2007/10/ascii_u ...