问题描述
如下面第一个图的九宫格中,放着 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];
  9     LL step;
 10 };
 11 Node s, e;
 12 const int N = 1e6;
 13 const int Next[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};//搜索的四个方向
 14 bool vis[N * 4];//标记数组
 15 int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};//前几个数的阶乘
 16 LL cantor(int s[])//康拓展开
 17 {
 18     LL ans = 0;
 19     int n = 9;
 20     for (int i = 0; i < n - 1; i++)
 21     {
 22         int tmp = 0;
 23         for (int j = i + 1; j < n; j++)
 24             if (s[j] < s[i])
 25                 tmp++;
 26         ans += fac[n - i - 1] * tmp;
 27     }
 28     return ans;
 29 }
 30 void cantor_reverse(int index, int a[])//康拓展开逆, 在本道题中未使用
 31 {
 32     index--;
 33     int n = 9;
 34     bool visit[9];
 35     memset(visit, false, sizeof(visit));
 36     for (int i = 0; i < n; i++)
 37     {
 38         int tmp = index / fac[n - i - 1];
 39         for (int j = 0; j <= tmp; j++)
 40             if (visit[j])
 41                 tmp++;
 42         a[i] = tmp + 1;
 43         visit[tmp] = true;
 44         index %= fac[n - i - 1];
 45     }
 46 }
 47 bool ischecked(int row, int col)//检查是否满足移动的条件
 48 {
 49     return (row > 0 && col > 0 && row < 4 && col < 4);
 50 }
 51 bool matched(Node node)//看是否达到给定的状态
 52 {
 53     for (int i = 0; i < 9; 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 = 0;
 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 = 0; pos < 9; pos++)
 73             if (p.cur[pos] == 9)//将"."当成9来计算
 74                 break;
 75         int row, col, new_row, new_col;
 76         row = pos / 3 + 1;
 77         col = pos % 3 + 1;
 78         for (int i = 0; i < 4; i++)
 79         {
 80             new_row = row + Next[i][0];
 81             new_col = col + Next[i][1];
 82             if (ischecked(new_row, new_col))//判断是否满足可移动的条件
 83             {
 84                 q = p;
 85                 q.step = p.step + 1;
 86                 //下面三步是交换这两个数(也就是移动到空位去)
 87                 int t = q.cur[(row - 1) * 3 + col - 1];
 88                 q.cur[(row - 1) * 3 + col - 1] = q.cur[(new_row - 1) * 3 + new_col - 1];
 89                 q.cur[(new_row - 1) * 3 + new_col - 1] = 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;//找不到就返回-1
104 }
105 int main()
106 {
107     char sta[10], en[10];
108     scanf("%s %s", sta, en);
109     for (int i = 0; i < 9; i++)
110         if (sta[i] != '.')
111             s.cur[i] = sta[i] - '0';
112         else
113             s.cur[i] = 9;//将'.'看成9
114     for (int i = 0; i < 9; i++)
115         if (en[i] != '.')
116             e.cur[i] = en[i] - '0';
117         else
118             e.cur[i] = 9;
119     LL tmp = bfs();
120     printf("%lld\n", tmp);
121
122     return 0;
123 }

View Code

转载于:https://www.cnblogs.com/Howe-Young/p/4351882.html

九宫重拍(bfs + 康拓展开)相关推荐

  1. 【蓝桥杯】九宫重排(BFS+康拓展开)

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

  2. 【 HDU1043-经典BFS+康拓展开 八数码】 (待更)

    给定一个序列,由1~8数字和字母x组成,表示的是一个3*3的矩形.每次操作x都能与相邻的数字交换,问如何操作才能使得序列为{1,2,3,4,5,6,7,8,x}. //多组数据-需要计算全部路径后直接 ...

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

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

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

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

  5. 九宫重排_康拓展开_bfs

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

  6. 八数码(康拓展开标记)及类似题

    文章:https://www.cnblogs.com/Mychael/p/8282895.html 康拓展开,知道数列求排名 //3 2 5 4 1 59 #include<bits/stdc+ ...

  7. 【康拓展开逆康托展开】

    百度百科就够了 自己的体会: 康托展开是基于比他小的前面的个数来进行计算的        另外康托展开也是一个数组到一个数的映射,因此也是可用于hash,用于空间压缩.比如在保存一个序列,我们可能需要 ...

  8. java 指令重拍_我发现我的Java重拍了!

    java 指令重拍 在一月份,我写了一篇文章,介绍了一些我希望在Java语言中看到的变化,这些变化会让我更加喜欢它(并使它变得更现代). 很多人建议使用许多JVM语言,但我很大程度上不予理会,因为这不 ...

  9. 《权力的游戏》第八季剧情翻水:超40万粉丝请愿重拍

    <权力的游戏>即将迎来大结局,在本周倒数第二集播出之后,剧情引发大量吐槽,愤怒的粉丝甚至在网上发起请愿,要求重拍<权力的游戏>第八季. 目前,已经有超过40万名网友在chang ...

最新文章

  1. java udp tcp协议_【java】TCP和UDP传输协议
  2. Code:blocks 调试经历,调试成功这其一
  3. scrum立会报告+燃尽图(第三周第七次)
  4. hdu 1560 DNA sequence(迭代加深搜索)
  5. DSDV的问题(Problems of DSDV)
  6. ArcGIS API for Javascript之专题图的制作(四)热力图渲染(上)
  7. eclipse使用配置教程
  8. 洛谷——P1375 小猫
  9. 视频教程-零基础Python自动化办公(漫画版)-Python
  10. 分分钟用上C#中的委托和事件
  11. 数字功放和模拟功放差异介绍
  12. spinal HDL - 01 - 环境搭建与Scala编程指南
  13. ARM安装python模块
  14. 认知科学与心理科学优质资源索引 ← 转自阳志平的个人网站
  15. PMP相位测量轮廓术基本原理介绍
  16. HTML5 新增input属性
  17. div 内 图片 垂直居中
  18. C语言实现 动态数组 处理任意类型数据
  19. 7个Linux手机平台比较 (1):进程间通信的异同
  20. 彼岸花的传说——附三色彼岸花图

热门文章

  1. VBS调用Windows API函数
  2. 如何在Pinterest投放广告呢?Pinterest广告推广形式!
  3. 第一,二,三范式,满足不满足的实例
  4. c语言123l表示什么,C语言的基本数据类型及其表示
  5. C语言接龙,C语言完成成语接龙小游戏
  6. 会声会影2020对比Vegas pro17,两款最新视频制作软件下载使用区别对比
  7. 【正版软件】威力导演16 LE版 附激活码
  8. Kamiya丨Kamiya艾美捷抗-C-Myc,多克隆说明书
  9. 国外中小学计算机老师待遇,美国中小学老师有职称评定吗?待遇如何?
  10. python 职业技能大赛备赛(2)