历届试题 九宫重排 (bfs+康托展开(哈希))

2024-01-25 00:18

本文主要是介绍历届试题 九宫重排 (bfs+康托展开(哈希)),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题描述

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

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

  输入第一行包含九宫的初态,第二行包含九宫的终态。

输出格式

  输出最少的步数,如果不存在方案,则输出-1。

样例输入

12345678.
123.46758
13524678.
46758123.

样例输出

3
22

解题思路

搜索的过程容易想,主要在于已经经过的状态的标记, map<string,int> m a p < s t r i n g , i n t > 会超时,上一年这样超时,今年还是这样,感觉一年什么都没做 ̄へ ̄
第一种方法是将string改成int做key,即将经过的状态装换成整数来标记;
第二种方法是使用康托展开,也就是相当于一种哈希的方法了,这样开一个大概4100000的数组就可以标记了,效率也更快一些.

代码实现

map<int,int> m a p < i n t , i n t >

#include<iostream>
#include<cstring>
#include<map>
#include<cstdio>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 19;
map<int, int> vis;
char str[maxn],str0[maxn],str1[maxn];
struct node{char str[maxn];int pos;int step;
}temp,ne;
int ans=INF;
int tranverse(char s[])
{int res=0;for(int i=0;i<10;i++){res=(res*10+(s[i]-'0'));}return res;
}
void BFS()
{queue<node>qu;int inter=tranverse(str0);vis[inter]=1;int mark=-1;for(int i=0;i<maxn;i++) {if(str0[i]=='.'){mark=i;break;}}strcpy(temp.str,str0);temp.step=0,temp.pos=mark;qu.push(temp);while(!qu.empty()){temp=qu.front();qu.pop();int p=temp.pos;if(strcmp(temp.str,str1)==0){ans=min(ans,temp.step);continue;}if(temp.step>=ans){continue;}if(p%3!=0){   //i-1strcpy(str,temp.str);str[p]=str[p-1];str[p-1]='.';int inter=tranverse(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p-1;qu.push(ne);}}if(p%3!=2){   //i+1strcpy(str,temp.str);str[p]=str[p+1];str[p+1]='.';int inter=tranverse(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p+1;qu.push(ne);}}if(p/3!=2){    //i+3strcpy(str,temp.str);str[p]=str[p+3];str[p+3]='.';int inter=tranverse(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p+3;qu.push(ne);}}if(p>=3){    //i-3strcpy(str,temp.str);str[p]=str[p-3];str[p-3]='.';int inter=tranverse(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p-3;qu.push(ne);}}}
}int main()
{cin>>str0>>str1;BFS();if(ans==INF){printf("-1\n");}else{printf("%d\n",ans);}return 0;
}

康托展开

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 4200000;
const int maxx =10;
int fac[maxx],ans=INF; 
char str[maxx],str0[maxx],str1[maxx];
bool vis[maxn];
struct node{char str[maxx];int step;int pos;
}temp,ne;
void init()
{fac[0]=1;for(int i=1;i<maxx;i++){fac[i]=fac[i-1]*i;}
}
int gethash(char str[])
{int res=0;for(int i=0;i<maxx;i++){int countt=0;for(int j=i+1;j<maxx;j++){if(str[i]>str[j]){countt++;}}res+=countt*fac[8-i];}return res;
}
void BFS()
{queue<node>qu;vis[gethash(str0)]=1;int mark=-1;for(int i=0;i<maxx;i++) {if(str0[i]=='.'){mark=i; str0[i]='0';}if(str1[i]=='.')  str1[i]='0';} strcpy(temp.str,str0);temp.step=0,temp.pos=mark;qu.push(temp);while(!qu.empty()){temp=qu.front();qu.pop();int p=temp.pos;if(strcmp(temp.str,str1)==0){ans=min(ans,temp.step);continue;}if(temp.step>=ans){continue;}if(p%3!=0){   //i-1strcpy(str,temp.str);str[p]=str[p-1];str[p-1]='0';int inter=gethash(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p-1;qu.push(ne);}}if(p%3!=2){   //i+1strcpy(str,temp.str);str[p]=str[p+1];str[p+1]='0';int inter=gethash(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p+1;qu.push(ne);}}if(p/3!=2){    //i+3strcpy(str,temp.str);str[p]=str[p+3];str[p+3]='0';int inter=gethash(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p+3;qu.push(ne);}}if(p>=3){    //i-3strcpy(str,temp.str);str[p]=str[p-3];str[p-3]='0';int inter=gethash(str);if(!vis[inter]){vis[inter]=1;strcpy(ne.str,str);ne.step=temp.step+1,ne.pos=p-3;qu.push(ne);}}}
}
int main()
{init();scanf("%s %s",str0,str1);BFS();printf("%d\n",ans);return 0;
}

这篇关于历届试题 九宫重排 (bfs+康托展开(哈希))的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/641502

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题是由安全生产模拟考试一点通提供,流动式起重机司机证模拟考试题库是根据流动式起重机司机最新版教材,流动式起重机司机大纲整理而成(含2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题参考答案和部分工种参考解析),掌握本资料和学校方法,考试容易。流动式起重机司机考试技

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

POJ 3057 最大二分匹配+bfs + 二分

SampleInput35 5XXDXXX...XD...XX...DXXXXX5 12XXXXXXXXXXXXX..........DX.XXXXXXXXXXX..........XXXXXXXXXXXXX5 5XDXXXX.X.DXX.XXD.X.XXXXDXSampleOutput321impossible

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

哈希表的底层实现(1)---C++版

目录 哈希表的基本原理 哈希表的优点 哈希表的缺点 应用场景 闭散列法 开散列法 开放定值法Open Addressing——线性探测的模拟实现 超大重点部分评析 链地址法Separate Chaining——哈希桶的模拟实现 哈希表(Hash Table)是一种数据结构,它通过将键(Key)映射到值(Value)的方式来实现快速的数据存储与查找。哈希表的核心概念是哈希

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"