当前位置: 首页 > news >正文

八数码问题

类似于拼图游戏,只能移动和空白格相同的四周的格子,从初始状态到目标状态的最少步数。

 

很容易想到是bfs,至于具体怎么实现,关键点是状态的定义,定义的好事半功倍。

bfs里面有一个vis数组,如果你用一个vis[][][][][][][][][],9维的数组来标记,是不合理的,数组也开不下,99

有hash可以帮忙,这里有两个方案,一个是自己写编码,解码的,其实和hash原理类似。具体的编码解码都只是一种策略。

记得数据结构考试的时候,有一道题目说是要怎么解决hash冲突,我就是写的加一个链表。后来听说不是这么做的,说什么直接加到后面一个单元,我觉得还不如加一个链表。

看了一下刘汝佳的写法,果然和我的思路相同,也是加一个链表。

然后最简单的方案就是stl里面的set了。

 

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 typedef int State[9];
  6 const int maxstadt = 1000000;
  7 State st[maxstadt],goal;
  8 
  9 int dist[maxstadt];
 10 
 11 const int dx[] = {-1,1,0,0};
 12 const int dy[] = {0,0,-1,1};
 13 
 14 /*
 15 int vis[362880],fact[9];
 16 
 17 void init_lookup_table() {
 18     fact[0] = 1;
 19     for(int i=1;i<9;i++)
 20         fact[i] = fact[i-1]*i;
 21 }
 22 
 23 int try_to_insert(int s) {
 24     int code = 0;
 25     for(int i=0;i<9;i++) {
 26         int cnt = 0;
 27         for(int j=i+1;j<9;j++)
 28             if(st[s][j]<st[s][i])
 29                 cnt++;
 30         code +=fact[8-i]*cnt;
 31     }
 32     if(vis[code]) return 0;
 33     return vis[code] = 1;
 34 }
 35 */
 36 
 37 /*
 38 set<int> vis;
 39 void init_lookup_table() {vis.clear();}
 40 int try_to_insert(int s) {
 41     int v = 0;
 42     for(int i=0;i<9;i++)
 43         v = v*10 + st[s][i];
 44     if(vis.count(v)) return 0;
 45     vis.insert(v);
 46     return 1;
 47 }
 48 */
 49 
 50 const int hashsize = 1000003;
 51 int head[hashsize],next[hashsize];
 52 void init_lookup_table() {memset(head,0,sizeof(head));}
 53 int hash(State& s) {
 54     int v;
 55     for(int i=0;i<9;i++)
 56         v = v*10 + s[i];
 57     return v % hashsize;
 58 }
 59 
 60 int try_to_insert(int s) {
 61     int h = hash(st[s]);
 62 
 63     int u = head[h];
 64     while(u) {
 65         if(memcmp(st[u],st[s],sizeof(st[s]))==0) return 0;
 66         u = next[u];
 67     }
 68     next[s] = head[h];
 69     head[h] = s;
 70     return 1;
 71 }
 72 
 73 
 74 
 75 int bfs() {
 76     init_lookup_table();
 77     int front=1,rear =2;
 78     while(front<rear) {
 79         State& s = st[front];
 80         if(memcmp(s,goal,sizeof(s))==0) return front;
 81 
 82         int z;
 83         for(z=0;z<9;z++)
 84             if(!s[z]) break;
 85 
 86         int x = z/3,y=z%3;
 87         for(int d=0;d<4;d++) {
 88             int newx = x + dx[d];
 89             int newy = y + dy[d];
 90 
 91             int newz = newx*3 + newy;
 92             if(newx>=0&&newx<3&&newy>=0&&newy<3) {
 93                 State& t = st[rear];
 94                 memcpy(&t,&s,sizeof(s));
 95 
 96                 t[newz] = s[z];
 97                 t[z] = s[newz];
 98                 dist[rear] = dist[front]+1;
 99                 if(try_to_insert(rear)) rear++;
100             }
101         }
102         front++;
103     }
104     return 0;
105 }
106 
107 int main()
108 {
109     freopen("in.txt","r",stdin);
110     for(int i=0;i<9;i++)
111         scanf("%d",&st[1][i]);
112 
113     for(int i=0;i<9;i++)
114         scanf("%d",&goal[i]);
115 
116     int ans = bfs();
117     if(ans>0)
118         printf("%d\n",dist[ans]);
119     else printf("-1\n");
120 
121     return 0;
122 }

 Tip:hash的解决方案模板

int insert(/*结点*/ s) {
    int h = hash(str(s));    //hash值
    int u = head[h];        //这个hash值对应的最后一个*结点*,也可以说是表头或者表尾,我个人理解表尾
    while(u) {
         //依次检查 查到return 0;
          u = next[u];
    }
    next[s] = head[h];        // 结点 s 的下一个结点
      head[h] = s;
      return 1;
}

 

转载于:https://www.cnblogs.com/TreeDream/p/6374830.html

相关文章:

  • 网络工程师--Vlan
  • 设计中的同理心
  • Stardew Valley(星露谷物语)Mod开发之路 1环境配置
  • 充分发挥行销效力的九个技巧
  • 远行
  • JavaScript数据类型
  • 关于许多人一直关注该怎么唱好高音的问题...
  • thinkphp-删除delete函数
  • escape()、encodeURI()、encodeURIComponent()区别详解
  • Apache(httpd) 报错You don't have permission to access /on this server.
  • 项目开发流程规范文档
  • 存储过程3. 参数的引入
  • UML概况
  • 引入类别解决所有键盘遮挡输入框的问题(iOS Object-C)
  • 对付CC攻击不必动用防火墙df
  • 【Leetcode】101. 对称二叉树
  • 77. Combinations
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Angular Elements 及其运作原理
  • Bytom交易说明(账户管理模式)
  • css布局,左右固定中间自适应实现
  • ES6 学习笔记(一)let,const和解构赋值
  • java中具有继承关系的类及其对象初始化顺序
  • React中的“虫洞”——Context
  • REST架构的思考
  • springboot_database项目介绍
  • 闭包--闭包作用之保存(一)
  • 大整数乘法-表格法
  • 将 Measurements 和 Units 应用到物理学
  • 深入浏览器事件循环的本质
  • 收藏好这篇,别再只说“数据劫持”了
  • 数组的操作
  • 小而合理的前端理论:rscss和rsjs
  • 中文输入法与React文本输入框的问题与解决方案
  • !!Dom4j 学习笔记
  • #FPGA(基础知识)
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (ZT)薛涌:谈贫说富
  • (二)springcloud实战之config配置中心
  • (九)信息融合方式简介
  • (四)鸿鹄云架构一服务注册中心
  • (转载)Linux 多线程条件变量同步
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET Core 中插件式开发实现
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .Net IOC框架入门之一 Unity
  • .net开发时的诡异问题,button的onclick事件无效
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • /usr/bin/env: node: No such file or directory
  • @Bean注解详解
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [14]内置对象
  • [C++]Leetcode17电话号码的字母组合
  • [CISCN2021 Quals]upload(PNG-IDAT块嵌入马)
  • [IE编程] 打开/关闭IE8的光标浏览模式(Caret Browsing)