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

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
  输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
样例输出
3
样例输入
13524678.
46758123.
样例输出
22
==========================分割线==================================
 
这个题刚开始直接用bfs去做,但是开的标记数组的维数会非常高,后来才在网上看到用康拓展开,能用到康拓展开是因为这可以看成是一个序列,所以可以用康拓展开求出他在全排列中的次序,这样标记数组就可以开一维的了,这道题的广搜和三个水杯那个题差不多
代码如下:
  1. #include<iostream>
  2. #include <cstdio>
  3. #include <queue>
  4. #include <cstring>
  5. using namespace std;
  6. typedef long long LL;
  7. struct Node{
  8. int cur[];
  9. LL step;
  10. };
  11. Node s, e;
  12. const int N = 1e6;
  13. const int Next[][] = {{, }, {, }, {-, }, {, -}};//搜索的四个方向
  14. bool vis[N * ];//标记数组
  15. int fac[] = {, , , , , , , , , };//前几个数的阶乘
  16. LL cantor(int s[])//康拓展开
  17. {
  18. LL ans = ;
  19. int n = ;
  20. for (int i = ; i < n - ; i++)
  21. {
  22. int tmp = ;
  23. for (int j = i + ; j < n; j++)
  24. if (s[j] < s[i])
  25. tmp++;
  26. ans += fac[n - i - ] * tmp;
  27. }
  28. return ans;
  29. }
  30. void cantor_reverse(int index, int a[])//康拓展开逆, 在本道题中未使用
  31. {
  32. index--;
  33. int n = ;
  34. bool visit[];
  35. memset(visit, false, sizeof(visit));
  36. for (int i = ; i < n; i++)
  37. {
  38. int tmp = index / fac[n - i - ];
  39. for (int j = ; j <= tmp; j++)
  40. if (visit[j])
  41. tmp++;
  42. a[i] = tmp + ;
  43. visit[tmp] = true;
  44. index %= fac[n - i - ];
  45. }
  46. }
  47. bool ischecked(int row, int col)//检查是否满足移动的条件
  48. {
  49. return (row > && col > && row < && col < );
  50. }
  51. bool matched(Node node)//看是否达到给定的状态
  52. {
  53. for (int i = ; i < ; i++)
  54. if (node.cur[i] != e.cur[i])
  55. return false;
  56. return true;
  57. }
  58. LL bfs()
  59. {
  60. memset(vis, false, sizeof(vis));
  61. queue<Node> Q;
  62. s.step = ;
  63. Q.push(s);
  64. Node p, q;
  65. int start_num = cantor(s.cur);
  66. vis[start_num] = true;//标记第一个元素
  67. while (!Q.empty())
  68. {
  69. p = Q.front();
  70. Q.pop();
  71. int pos;
  72. for (pos = ; pos < ; pos++)
  73. if (p.cur[pos] == )//将"."当成9来计算
  74. break;
  75. int row, col, new_row, new_col;
  76. row = pos / + ;
  77. col = pos % + ;
  78. for (int i = ; i < ; i++)
  79. {
  80. new_row = row + Next[i][];
  81. new_col = col + Next[i][];
  82. if (ischecked(new_row, new_col))//判断是否满足可移动的条件
  83. {
  84. q = p;
  85. q.step = p.step + ;
  86. //下面三步是交换这两个数(也就是移动到空位去)
  87. int t = q.cur[(row - ) * + col - ];
  88. q.cur[(row - ) * + col - ] = q.cur[(new_row - ) * + new_col - ];
  89. q.cur[(new_row - ) * + new_col - ] = t;
  90. if (matched(q))//如果找到之后直接返回
  91. {
  92. return q.step;
  93. }
  94. int num = cantor(q.cur);
  95. if (!vis[num])
  96. {
  97. vis[num] = true;
  98. Q.push(q);
  99. }
  100. }
  101. }
  102. }
  103. return -;//找不到就返回-1
  104. }
  105. int main()
  106. {
  107. char sta[], en[];
  108. scanf("%s %s", sta, en);
  109. for (int i = ; i < ; i++)
  110. if (sta[i] != '.')
  111. s.cur[i] = sta[i] - '';
  112. else
  113. s.cur[i] = ;//将'.'看成9
  114. for (int i = ; i < ; i++)
  115. if (en[i] != '.')
  116. e.cur[i] = en[i] - '';
  117. else
  118. e.cur[i] = ;
  119. LL tmp = bfs();
  120. printf("%lld\n", tmp);
  121.  
  122. return ;
  123. }

九宫重拍(bfs + 康拓展开)的更多相关文章

  1. 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 ...

  2. bnuoj 1071 拼图++(BFS+康拓展开)

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=1071 [题意]:经过四个点的顺逆时针旋转,得到最终拼图 [题解]:康拓展开+BFS,注意先预处理,得 ...

  3. 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 ...

  4. 8数码,欺我太甚!<bfs+康拓展开>

    不多述,直接上代码,至于康拓展开,以前的文章里有 #include<iostream> #include<cstdio> #include<queue> using ...

  5. hdu-1043 bfs+康拓展开hash

    因为是计算还原成一种局面的最短步骤,应该想到从最终局面开始做bfs,把所有能到达的情况遍历一遍,把值存下来. bfs过程中,访问过的局面的记录是此题的关键,9*9的方格在计算过程中直接存储非常占内存. ...

  6. HDU 4531 bfs/康拓展开

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

  7. 蓝桥杯 历届试题 九宫重排 (bfs+康托展开去重优化)

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

  8. cdoj 414 八数码 (双向bfs+康拓展开,A*)

    一道关乎人生完整的问题. DBFS的优越:避免了结点膨胀太多. 假设一个状态结点可以扩展m个子结点,为了简单起见,假设每个结点的扩展都是相互独立的. 分析:起始状态结点数为1,每加深一层,结点数An ...

  9. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

随机推荐

  1. uva 1378 A Funny Stone Game (博弈-SG)

    题目链接:http://vjudge.net/problem/viewProblem.action?id=41555 把第i堆的每个石子看出一堆个数为n-i的石子,转换为组合游戏 #include & ...

  2. jQuery图片滑动

    一个非常简单实用的jQuery插件 可以用在页面的顶部广告展示 http://slidesjs.com/ 一个需要注意的问题, 就是在手机等客户端(IOS8以上), 使用此插件时, 经常会触发插件的r ...

  3. Linux 4.1内核编译报告

    编译环境 Arch Linux on VirtualBox 下载内核 https://www.kernel.org/ 下载的内核压缩包,此时的最新内核版本为4.1: 解压包 # tar -xvJf l ...

  4. CentOS 6.5下安装MySql 5.7

    不管您按下面的方法安装成功否,请留个言,把您遇到的问题写上共勉! 包下载http://url.cn/WrNg5S 环境: 1).软硬件:E6420双核CPU,8G内存,1T硬盘 2).虚拟机下 Cen ...

  5. C#.net 货币格式转换

    /// <summary> /// 输入Float格式数字,将其转换为货币表达方式 /// </summary> /// <param name="ftype& ...

  6. 19 Remove Nth Node From End of List(去掉链表中倒数第n个节点Easy)

    题目意思:去掉链表中倒数第n个节点 思路:1.两次遍历,没什么技术含量,第一次遍历计算长度,第二次遍历找到倒数第k个,代码不写了   2.一次遍历,两个指针,用指针间的距离去计算. ps:特别注意删掉 ...

  7. LoadRunner安装停在注册界面安装失败----解决办法之一

    今天下了个LoadRunner11.5玩玩,准备测手头上准备发布的项目性能,结果安装的时候,报错“Error Creating system registry entry”,在51testing搜索各 ...

  8. jQuery delegate方法实现Ajax请求绑定事件不丢失

    给元素绑定click事件后 ,遇到一个问题:当执行一些ajax请求,再次调用此页面,里面的这个click事件就失效了 比如说:我的分页是一个ajax请求 但我点下一页时 后生成的元素a就没有了clic ...

  9. Win7下启用IIS7

    1.进入“控制面板-->程序”: 2.点击“打开或关闭Windows功能” 3.选择“Internet信息服务”相关选项,如下: 点击“确定”后,请稍等.. 5.启用成功后,可在浏览器访问:ht ...

  10. debian小巧好看的桌面

    先看完,不然,你一定会后悔的..不好看,你打我.. sudo apt-get install xfce4 sudo apt-get install xfce4-goodies sudo apt-get ...