[题解] 八数码问题 (哈希表+搜索)
来源:互联网 发布:非结构化数据存储方案 编辑:程序博客网 时间:2024/05/18 01:10
题意: 3×3九宫棋盘,放置数码为1 -8的8个棋牌,剩下一个空格,只能通过棋牌向空格的移动来改变棋盘的布局。给出初始布局和目标布局,问最少多少步移动能够使初始布局变为目标布局
分析: 题目思路很清晰,直接广搜即可。但是问题是如何保存状态并且判重?我们对于每一个状态进行观察,均是由0-8构成的一个全排列,那么状态一共有9!=362880种,那么我们有多种方案进行保存,在这里我们只讨论两种
- 方案一:直接用一个九位数(或者数组)保存
- 方案二:将其映射到1~9!的编码中
我们可以将两种方法结合起来使用,用方案一来进行保存状态,用方案二来进行判重。方案一比较简单,方案二的实现具体有两种选择:
1.使用取余法放入哈希表,在这里使用拉链法或者是线性探查法或者双函数法等等等等都是可行的
2.利用此九位数可以转换成1~9全排列(每个加1)的性质,将它描述为
经过分析我们发现,第一种实现方案有冲突,但是哈希函数简单有效,判重操作较为简单;第二种实现方案完全避免了冲突,但是算出全排列编码的函数耗时较多,大家可以根据实际情况自由的选择
详细代码如下:
//全排列版#include <bits/stdc++.h>using namespace std;typedef pair <int,int> doub;int target=46685,num[10],number[10],w,sum,h,temp;bool vis[400000];queue<doub> q;int g(int x) { int ans=1; for(int i=1;i<=x;i++) { ans*=i; } return ans;} int hash() {//计算哈希函数 int ans=0; memset(number,0,sizeof(number)); for(int i=1;i<=9;i++) { for(int j=9;j>num[i];j--) { number[j]++; } ans+=(num[i]-number[num[i]]-1)*g(9-i); } return ans;}void work1(int now) { for(int i=9;i>=1;i--) { num[i]=now%10; if(num[i]==1) w=i; now=now/10; } return ;}int work2() { int ans=0; for(int i=1;i<=9;i++) { ans=ans*10; ans+=num[i]; } return ans;}int main() { for(int i=1;i<=9;i++) num[i]=getchar()-'0'+1; target=hash();//获取目标状态 getchar(); for(int i=1;i<=9;i++) num[i]=getchar()-'0'+1; h=hash();//获取当前状态 vis[h]=true; q.push(doub{work2(),0}); while(!q.empty()) {//广搜 doub now=q.front();q.pop(); work1(now.first); h=hash(); if(h==target) { printf("%d",now.second); return 0; } if(w%3!=1) {//右移 temp=num[w];num[w]=num[w-1];num[w-1]=temp; h=hash(); if(!vis[h]) { vis[h]=true; q.push(doub{work2(),now.second+1}); } temp=num[w];num[w]=num[w-1];num[w-1]=temp; } if(w-3>0) {//下移 temp=num[w];num[w]=num[w-3];num[w-3]=temp; h=hash(); if(!vis[h]) { vis[h]=true; q.push(doub{work2(),now.second+1}); } temp=num[w];num[w]=num[w-3];num[w-3]=temp; } if(w%3!=0) {//左移 temp=num[w];num[w]=num[w+1];num[w+1]=temp; h=hash(); if(!vis[h]) { vis[h]=true; q.push(doub{work2(),now.second+1}); } temp=num[w];num[w]=num[w+1];num[w+1]=temp; } if(w+3<10) {//上移 temp=num[w];num[w]=num[w+3];num[w+3]=temp; h=hash(); if(!vis[h]) { vis[h]=true; q.push(doub{work2(),now.second+1}); } temp=num[w];num[w]=num[w+3];num[w+3]=temp; } }}
by:Chlience
- [题解] 八数码问题 (哈希表+搜索)
- 八数码问题(启发式搜索)
- 【启发式搜索】八数码问题
- A*搜索 - 八数码问题
- Vijos1360[八数码问题] 搜索
- 启发式搜索算法求解八数码问题(C)
- 八数码问题(状态空间搜索)--《算法入门经典》
- 暴力求解法_隐式图搜索(八数码问题)
- 八数码问题——A*搜索
- 启发式搜索程序设计-八数码问题
- Poj1077/HDU1043(A*搜索)八数码问题
- HDU 1043 八数码问题 A*搜索
- 八数码问题 经典搜索 bfs
- 搜索的分类及八数码问题
- Poj 1077 Eight 八数码问题 (搜索)
- POJ 1077 八数码问题 练习搜索
- HDU 1043 八数码问题 A*搜索
- 八数码问题:C++广度搜索实现
- Java调优经验谈
- [练习][ZOJ3515]优先队列 Middle number
- FPGA作业1:利用74138设计4-16译码器
- python3.5 Unable to find vcvarsall.bat
- 如何修改maven默认jdk配置
- [题解] 八数码问题 (哈希表+搜索)
- 关于NGUI与UGUI的区别
- 1046. Shortest Distance (20)
- 第七次作业
- 深度学习初学篇一
- 判断输入的三角形边长能否构成三角形
- HDU2674 N!Again 解题报告【阶乘】
- 计蒜客————跳跃游戏二
- 3、JACK Audio Connect Kit低延迟音频服务——Qjackctl基本设置