题目描述:

代码如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #define N  1000000
  5 #define HN 1000003
  6 #define LEN 9
  7
  8 int head[HN],next[N];
  9 int st[N][LEN], goal[LEN];
 10 int dis[N];    //记录步数
 11
 12 int Hash(int *st)//获取本次排列组合的哈希值
 13 {
 14     int i,v;
 15     v = 0;
 16     for (i=0 ; i<LEN ; i++)//得到一个LEN长度数值:v
 17     {
 18         v = v*10 + st[i];
 19     }
 20     return v%HN;//得到对应哈希值
 21 }
 22
 23
 24 // 功能:对本次的排列组合,若不在哈希表中,则在哈希表中进行键值映射
 25 int try_insert(int rear)//rear:本次组合的编号
 26 {
 27     int h = Hash(st[rear]);    //获得本次排列组合对应的哈希值
 28     int u = head[h];        //根据哈希值,获得哈希表中对应的键(key),若没有则为0
 29
 30     while (u)//当上一步有拿到键(key),查找对应的值(value->排列组合),
 31     {
 32         if (memcmp(st[u],st[rear],sizeof(st[0]))==0)//存在相同的值(value->排列组合)
 33             return 0;    //本次值(value->排列组合)将不记录,退出
 34         u = next[u];    //当前键(key)还有其他值,遍历获得其他值(value->排列组合)
 35     }
 36
 37     //当前值(value->排列组合)不在哈希表中,将进行记录
 38     next[rear] = head[h];    //当前键(key)的记录是否有其他值,若本身为新组合,为0;若为存在组合,则为其上一个编号(相同组合)
 39     head[h] = rear;            //哈希表中对应的键(key),更新为本次组合编号(rear)
 40     return 1;
 41 }
 42
 43 int bfs()
 44 {
 45     int d;
 46     int x,y,z,nx,ny,nz;
 47     int fron = 1,rear = 2;    //fron:当前排列组合;rear:移动后的排列组合
 48     const int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0},};
 49
 50     memset(head,0,sizeof(head));
 51     while (fron < rear)
 52     {
 53         if (memcmp(goal,st[fron],sizeof(st[0]))==0)//当前排列组合为目标排列组合
 54             return fron;
 55
 56         for (z=0 ; z<LEN ; z++)
 57         {
 58             if (st[fron][z]==0)//0即为对应的'.'
 59                 break;
 60         }
 61
 62         x = z/3,y = z%3;//获得'.'的坐标
 63         for (d=0 ; d<4 ; d++)
 64         {
 65             nx = x+dir[d][0];
 66             ny = y+dir[d][1];
 67             if (nx>=0 && nx<3 && ny>=0 && ny<3)
 68             {
 69                 nz = 3*nx+ny;//'.'将要移动的下一步位置
 70
 71                 memcpy(&st[rear],&st[fron],sizeof(st[0]));
 72                 st[rear][nz] = st[fron][z];
 73                 st[rear][z] = st[fron][nz];
 74
 75                 dis[rear] = dis[fron]+1;//记录步数
 76                 if (try_insert(rear))//对新排列组合进行查找
 77                     rear ++;//进队列
 78             }
 79         }
 80         fron ++;//出队列
 81     }
 82
 83     return 0;
 84 }
 85
 86 int main(void)
 87 {
 88     int i,ans;
 89     char s1[LEN+1],s2[LEN+1];
 90     memset(dis,0,sizeof(dis));
 91     scanf("%s%s",&s1,&s2);
 92
 93     for (i=0 ; i<LEN ; i++)//将'.'转换为0,便于计算哈希值
 94     {
 95         if (s1[i]=='.')
 96             st[1][i] = 0;
 97         else
 98             st[1][i] = s1[i]-'0';
 99
100         if (s2[i]=='.')
101             goal[i] = 0;
102         else
103             goal[i] = s2[i]-'0';
104     }
105
106     ans = bfs();
107     if (ans > 0)
108         printf("%d",dis[ans]);
109     else
110         puts("-1");
111
112     return 0;
113 }

C解法

解题思路:

本题要求最少步数转换成目标组合,广度优先遍历(BFS)可满足要求

每次对新组合进行检查时,需要较高的检索效率,

1.使用map或者set做检索时,其对应的检索效率低,超时不能满足题目需求;

2.对组合进行哈希判重,大大提高了检索效率;

关于本题的哈希判重,参考了:

https://blog.csdn.net/hao_zong_yin/article/details/62419919

https://www.cnblogs.com/acxblog/p/7253477.html

哈希判重,利用键-值映射,有效提高了搜索的效率;

1.建立键(key)表,head[NH],需初始化;建立值(value)表,next[N];

2.BFS搜索新组合,通过向不同方向移动 ' . ' (0)  得到新的组合;

3.根据新组合,计算对应的哈希值;

4.根据哈希值,进行检索决定是否添加新的排列组合

  4.1.插入的组合存在

  4.2.插入的组合不存在

5.若有新组合添加,队列+1(rear+1)

6.每次出列(fron+1),检查是否为目标组合

7.若fron > rear,则不存在方案,输出-1

转载于:https://www.cnblogs.com/mind000761/p/10572127.html

[蓝桥杯]PREV-19.历届试题_九宫重排相关推荐

  1. 蓝桥杯经典算法 不定方程解法 蓝桥杯练习系统 历届试题 买不到的数目

    蓝桥杯经典算法 第六讲 不定方程解法   蓝桥杯算法教学与培训_蓝桥杯经典算法 第六讲 不定方程解法 不定方程的一般解法   朴素算法 public static void main(String[] ...

  2. 蓝桥杯大学组python试题_第十届蓝桥杯2019年C/C++ 大学A组省赛试题

    2019年蓝桥杯第十届软件类省赛 C/C++ 大 学 A 组 试题 A: 平方和 本题总分:5 分 [问题描述] 小明对数位中含有 2.0.1.9 的数字很感兴趣,在 1 到 40 中这样的数包括 1 ...

  3. 蓝桥杯:BFS解决问题总结(九宫重排,跳蚱蜢,卡片交换)

    BFS标志: 初始状态经过演变到达目标状态,问最少经过几步 如九宫重排问题 跳蚱蜢问题: 卡片交换问题: 解题模板: 不同题目的move函数和move函数的个数不同,其他都是相同的 struct st ...

  4. 蓝桥杯,历届试题,九宫重排

    这题是寒假快要结束的时候做的(已经开学一周啦),因为自己写的代码有超时,百度后看了康托展开,然后优化成功,花了比较长的时间.题目如下: 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还 ...

  5. 蓝桥杯【历届试题】九宫重排

    原文:https://blog.csdn.net/qq_34594236/article/details/64446491 题目思路: 我们可以把每一种局面当作是一个结点.空白格可以向四个方向移动,移 ...

  6. 蓝桥杯练习系统历届试题 翻硬币

    问题描述 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如 ...

  7. “蓝桥杯”练习系统——历届试题

    1. 核桃的数量(水题) 思路:求两个数的最大公约数可以用欧几里得算法(辗转相除法),即 a与b的最大公约数 等于 b与(a对b取余) 的最大公约数,当b等于0时,a与b的最大公约数是a.两个数的最小 ...

  8. 蓝桥杯研究生c语言试题答案,蓝桥杯试题_蓝桥杯 你有蓝桥杯历年的试题吗最好有参考答案啊 高职高专组C语言的 有的话麻烦你发给我 万分感谢_淘题吧...

    ❶ 蓝桥杯 你有蓝桥杯历年的试题吗最好有参考答案啊. 高职高专组C语言的 有的话麻烦你发给我 万分感谢 我有真题.但是老师没给答案 ❷ 为什么蓝桥杯试题集评测老是错 楼上的网友说的很简单,实际上因为每 ...

  9. 蓝桥杯单片机国赛客观题_蓝桥杯单片机比赛历年试题获取

    蓝桥杯单片机比赛历年试题获取!!! 准备蓝桥杯蓝桥杯比赛除了对板子各个模块的熟悉外,还有一件事,那就是把它们综合起来运用.当你单独使用板子上的某一个模块时,可能不会有什么问题,甚至对已经反复练习过后的 ...

最新文章

  1. 机器学习中的梯度下降( Gradient Descent)算法
  2. (转)男人的真?。。。
  3. java 枚举 循环_java – 在枚举中实现内部接口时的循环继承
  4. c java http_[C] 类似于HttpClient的C语言实现Http POST功能如何实现?
  5. tomcat7.027-webSocket应用程序构建01
  6. 医学图像处理期末复习(一)
  7. Java架构师必须知道的 6 大设计原则
  8. (三)MySQL入门,看我就够了!!!
  9. 用枚举enum实现单例
  10. js判断浏览器是否支持flash的方法
  11. elf文件格式_elf文件,readelf
  12. NEC协议——红外遥控的使用
  13. JAVA水晶花数_我的世界Java版1.17快照20w45a新增物品详解
  14. android jersey 上传图片,图片上传--Jersey实现RESTful接口
  15. 中缀表达式转换为后缀表达式算法
  16. C语言数据结构之图的邻接矩阵的应用实例
  17. 超效率dea matlab,MATLAB在超效率DEA模型中的应用研究
  18. 新手上路,Python黑帽子学习笔记从此开篇
  19. activex 控件 过期_IE浏览器阻止过期ActiveX控件或将影响网银的使用-银行控件蓝屏...
  20. 三大抽样分布——卡方分布、t分布、F分布

热门文章

  1. win7怎么看服务器文件管理,Win7库文件管理器怎么用 Win7库功能及其使用方法详解...
  2. java forname 原理_Java Class.forName()用法和newInstance()方法原理解析
  3. python3 idle自动补全_给Python IDLE加上自动补全和历史功能
  4. redis 保存 array list 区别_Redis科普篇
  5. 报文解析_104规约报文结构解析
  6. 淘宝NPM镜像、cnmp
  7. c语言中热河输入空格,承德市2020年(春秋版)小学英语六年级上册期中考试模拟试卷(1)C卷...
  8. 使用计算机比喻的心理学研究取向,心理学入门:6个方面的研究取向
  9. oracle删错表了怎么办,Oracle中表被删除或数据被错误修改后的恢复方法
  10. php屏蔽审查元素,HTML网站右键禁用F12代码 屏蔽审查元素 防止修改页面代码