题目描述:

代码如下:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 1000000
#define HN 1000003
#define LEN 9 int head[HN],next[N];
int st[N][LEN], goal[LEN];
int dis[N]; //记录步数 int Hash(int *st)//获取本次排列组合的哈希值
{
int i,v;
v = ;
for (i= ; i<LEN ; i++)//得到一个LEN长度数值:v
{
v = v* + st[i];
}
return v%HN;//得到对应哈希值
} // 功能:对本次的排列组合,若不在哈希表中,则在哈希表中进行键值映射
int try_insert(int rear)//rear:本次组合的编号
{
int h = Hash(st[rear]); //获得本次排列组合对应的哈希值
int u = head[h]; //根据哈希值,获得哈希表中对应的键(key),若没有则为0 while (u)//当上一步有拿到键(key),查找对应的值(value->排列组合),
{
if (memcmp(st[u],st[rear],sizeof(st[]))==)//存在相同的值(value->排列组合)
return ; //本次值(value->排列组合)将不记录,退出
u = next[u]; //当前键(key)还有其他值,遍历获得其他值(value->排列组合)
} //当前值(value->排列组合)不在哈希表中,将进行记录
next[rear] = head[h]; //当前键(key)的记录是否有其他值,若本身为新组合,为0;若为存在组合,则为其上一个编号(相同组合)
head[h] = rear; //哈希表中对应的键(key),更新为本次组合编号(rear)
return ;
} int bfs()
{
int d;
int x,y,z,nx,ny,nz;
int fron = ,rear = ; //fron:当前排列组合;rear:移动后的排列组合
const int dir[][] = {{,},{,-},{,},{-,},}; memset(head,,sizeof(head));
while (fron < rear)
{
if (memcmp(goal,st[fron],sizeof(st[]))==)//当前排列组合为目标排列组合
return fron; for (z= ; z<LEN ; z++)
{
if (st[fron][z]==)//0即为对应的'.'
break;
} x = z/,y = z%;//获得'.'的坐标
for (d= ; d< ; d++)
{
nx = x+dir[d][];
ny = y+dir[d][];
if (nx>= && nx< && ny>= && ny<)
{
nz = *nx+ny;//'.'将要移动的下一步位置 memcpy(&st[rear],&st[fron],sizeof(st[]));
st[rear][nz] = st[fron][z];
st[rear][z] = st[fron][nz]; dis[rear] = dis[fron]+;//记录步数
if (try_insert(rear))//对新排列组合进行查找
rear ++;//进队列
}
}
fron ++;//出队列
} return ;
} int main(void)
{
int i,ans;
char s1[LEN+],s2[LEN+];
memset(dis,,sizeof(dis));
scanf("%s%s",&s1,&s2); for (i= ; i<LEN ; i++)//将'.'转换为0,便于计算哈希值
{
if (s1[i]=='.')
st[][i] = ;
else
st[][i] = s1[i]-''; if (s2[i]=='.')
goal[i] = ;
else
goal[i] = s2[i]-'';
} ans = bfs();
if (ans > )
printf("%d",dis[ans]);
else
puts("-1"); return ;
}

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

[蓝桥杯]PREV-19.历届试题_九宫重排的更多相关文章

  1. 蓝桥杯练习系统历届试题 剪格子 dfs

    问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+|10* 1|52|+--****--+|20|30* 1|*******--+| 1| 2| 3|+--+--+--+ ...

  2. 蓝桥杯练习系统历届试题 带分数 dfs

    问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. 注意特征:带分数中,数字1~9分别出现且只出现一次( ...

  3. [蓝桥杯]PREV-44.历届试题_青蛙跳杯子

    问题描述 X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色. X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去. 如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙 ...

  4. [蓝桥杯]PREV-10.历届试题_幸运数

    问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的“筛法”生成 . 首先从1开始写出自然数1,,,,,,.... 就是第一个幸运数. 我们从2这个数开始.把所有序号能被2整除的项删除,变 ...

  5. [蓝桥杯]PREV-27.历届试题_蚂蚁感冒

    问题描述 长100厘米的细长直杆子上有n只蚂蚁.它们的头有的朝左,有的朝右. 每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒. 当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行. 这些蚂蚁中,有1只蚂 ...

  6. [蓝桥杯]PREV-26.历届试题_最大子阵

    问题描述 给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大. 其中,A的子矩阵指在A中行和列均连续的一块. 输入格式 输入的第一行包含两个整数n, m,分别表示矩阵A的行数和 ...

  7. [蓝桥杯]PREV-25.历届试题_城市建设

    问题描述 栋栋居住在一个繁华的C市中,然而,这个城市的道路大都年久失修.市长准备重新修一些路以方便市民,于是找到了栋栋,希望栋栋能帮助他. C市中有n个比较重要的地点,市长希望这些地点重点被考虑.现在 ...

  8. [蓝桥杯]PREV-23.历届试题_数字游戏

    问题描述 栋栋正在和同学们玩一个数字游戏. 游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈.栋栋首先说出数字1.接下来,坐在栋栋左手边的同学要说下一个数字2.再下面的一个同学要从上一个同学说的数 ...

  9. [蓝桥杯]PREV-22.历届试题_国王的烦恼

    问题描述 C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在多座桥连接.然而,由于海水冲刷,有一些大桥面临着不能使用的危险. 如果两个小岛间 ...

随机推荐

  1. javascript 中的原型继承

    javascript圆形变成的基本规则: 所有数据都是对象: 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它: 对象会记住它的原型: 如果对象无法响应某个请求,它会把这个请求委托给 ...

  2. Hadoop集群启动

    1.初始化集群 要启动Hadoop集群,需要启动HDFS和YARN两个集群 注意:首次启动HDFS时,必须对其进行格式化操作.本质上是一些清理和准备工作, 因为此时的HDFS在物理上还是不存在的 命令 ...

  3. python常量 变量 数据类型 注释 交互 if语句

    1.认识python python的创始人吉多·范罗苏姆(Guido van Rossum )龟叔在89年圣诞节开始开发python python属于解释型语言,强类型定义语言. 编译型/解释型:编译 ...

  4. linux 安装 ftp 实现文件共享

    转载:http://blog.sina.com.cn/s/blog_165e646820102xe1q.html 参考:1.http://www.cnblogs.com/mrcln/p/6179673 ...

  5. openSUSE安装Qt5

    找了很多资料发现没一个好用又简单的. 终于在wiki.qt.io上找到了一个! 安装方法如下: 1下载安装包,我建议最好下载离线包.下载链接http://download.qt.io/archive/ ...

  6. linux 中 nginx配置

    1.nginx中include的使用 在/usr/local/nginx/conf/nginx.conf中可以使用include去加载其他配置文件: 例如:include vhost/*.conf; ...

  7. 2018-4-12 数学建模MATLAB常用的一些函数

    一.求函数的极限问题 limit(fun,x,y,str) 意义:fun为所求极限的函数,x代表变量,y代表变量的极限值,str代表这个极限的类型,常用的参数是right,left. 如果是多个变量的 ...

  8. appium---android元素定位

    原文链接:https://www.cnblogs.com/meitian/p/6103391.html 一.常用识别元素的工具 uiautomator:Android SDK自带的一个工具,在tool ...

  9. 关于Spring中的<context:annotation-config/>配置(开启注解)

    当我们需要使用BeanPostProcessor时,直接在Spring配置文件中定义这些Bean显得比较笨拙,例如: 使用@Autowired注解,必须事先在Spring容器中声明AutowiredA ...

  10. Request、Response

    Request Request对象在我们写爬虫发送请求的时候调用,参数如下: url: 就是需要请求的url callback: 指定该请求返回的Response由那个函数来处理. method: 请 ...