挺不错的题目,很锻炼代码能力和调试能力~

题意:初始格子状态固定,给你移动后格子的状态,问最少需要多少步能到达,如果步数大于30,输出-1。

由于单向搜索状态太多,搜到二十几就会爆了,所以应该想到双向广搜。

对于每一个格子,我只需要记录上面和前面的格子颜色,因为格子左右移动前面颜色不变上面颜色变了,前后移动的话只是前面和上面的颜色交换了而已,不过写的太挫了。。。应该直接进制压缩一下。。。我还用了两个数来表示前面和上面的颜色,下次把这些搜索题全A了后再回来重新写一下,重写效果也会不错,并不是题目a了这题就好了。

#include <stdio.h>
#include <string.h>#define LL __int64const int mod = 100007;
struct HASH{int head[mod+10], E, next[222222];int v1[222222], v2[222222], c[222222];void init() {memset(head, -1, sizeof(head));E = 0;}int gethash(int x,int y) {return (((LL)x + y)%mod+mod)%mod;}int isin(int x, int y) {int u = gethash(x, y);for(int i = head[u];i != -1;i = next[i]) {if(v1[i] == x && v2[i] == y) return c[i];}return -1;}void push(int x, int y, int step) {int u = gethash(x, y);v1[E] = x;v2[E] = y;c[E] = step;next[E] = head[u];head[u] = E++;}
}ha1, ha2;struct PP{int st1, st2;int step;PP(){}PP(int st1, int st2, int step) : st1(st1), st2(st2), step(step) {}
}cur, to, q[1000002];int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int a[22], b[22], d[2222];void swap(int &a, int &b) {int t = a; a = b; b = t;
}void get_zt(int st1, int st2) {for(int i = 9;i >= 1;i --)  a[i] = st1%10, st1 /= 10;for(int i = 9;i >= 1;i --)  b[i] = st2%10, st2 /= 10;
}void get_xy(int &st1, int &st2) {st1 = st2 = 0;for(int i = 1;i <= 9; i++)  st1 = st1*10+a[i];for(int i = 1;i <= 9; i++)  st2 = st2*10+b[i];
}bool judge(int go) {int ret = 0;for(int i = 1;i <= 9; i++)  ret = ret*10+a[i];return go == ret;
}int getnew(int a, int b) {int vis[5], i;for(i = 1;i <= 3; i++) vis[i] = 0;vis[a]++;vis[b]++;for(i = 1;i <= 3; i++)  if(!vis[i]) return i;
}int min(int a, int b) {return a>b?b:a;
}int bfs(int st1,int st2, int go) {ha1.init();ha1.push(st1, st2, 0);int head = 0, tail = 0;q[tail++] = PP(st1, st2, 0);int i, j, k;while(head < tail) {cur = q[head++];st1 = cur.st1, st2 = cur.st2;get_zt(st1, st2);int now ;for(i = 1;i <= 9; i++)  if(a[i] == 4) {now = i; break;}int x = now/3+1, y = now%3;if(y == 0)  y = 3, x--;for(i = 0;i < 4; i++) {int xx = x+dx[i];int yy = y+dy[i];if(xx < 1 || xx > 3 || yy < 1 || yy > 3)    continue;int then = (xx-1)*3+yy;swap(a[now], a[then]);swap(b[now], b[then]);if(i < 2) {swap(a[now], b[now]);if(judge(go)) {return cur.step+1;}get_xy(to.st1, to.st2);to.step = cur.step+1;if(ha1.isin(to.st1, to.st2) == -1 && to.step <= 20) {ha1.push(to.st1, to.st2, to.step);if(to.step > 20)   continue;q[tail++] = to;}swap(a[now], b[now]);}else {a[now] = getnew(a[now], b[now]);if(judge(go)) {return cur.step+1;}get_xy(to.st1, to.st2);to.step = cur.step+1;if(ha1.isin(to.st1, to.st2) == -1 && to.step <= 20) {ha1.push(to.st1, to.st2, to.step);if(to.step > 20)   continue;q[tail++] = to;}a[now] = getnew(a[now], b[now]);}swap(a[now], a[then]);swap(b[now], b[then]);}}int temp , tot = 0;int N = 1<<8;for(i = 0;i < N; i++) {temp = go;for(j = 9;j >= 1; j--)a[j] = temp%10 , temp /= 10;int id1 = 1, id2 = 0, sum = 0;while(id1 <= 9) {if(a[id1] == 4) {sum = sum*10+4;id1++;continue;}if((1<<id2) & i) {for(k = 3;k >= 1; k--)   if(k != a[id1])    break;sum = sum*10+k;}else {for(k = 1;k <= 3; k++)   if(k != a[id1])    break;sum = sum*10+k;}id1++, id2++;}d[tot++] = sum;}for(i = 0;i < tot; i++){int now = ha1.isin(go, d[i]);if(now >= 0)    return now;}int ans = 1111111;for(int ii = 0;ii < tot;ii++) {ha2.init();cur = PP(go, d[ii], 0);int head = 0, tail = 0;q[tail++] = cur;int ok = 0;while(head < tail) {cur = q[head++];st1 = cur.st1, st2 = cur.st2;get_zt(st1, st2);int now ;for(i = 1;i <= 9; i++)  if(a[i] == 4) {now = i; break;}int x = now/3+1, y = now%3;if(y == 0)  y = 3, x--;for(i = 0;i < 4; i++) {int xx = x+dx[i];int yy = y+dy[i];if(xx < 1 || xx > 3 || yy < 1 || yy > 3)    continue;int then = (xx-1)*3+yy;swap(a[now], a[then]);swap(b[now], b[then]);if(i < 2) {swap(a[now], b[now]);get_xy(to.st1, to.st2);to.step = cur.step+1;int temp = ha1.isin(to.st1, to.st2);if(temp >= 0)  {ok = 1;ans = min(ans, temp+to.step);continue;}if(ha2.isin(to.st1, to.st2) == -1 && to.step <= 10) {ha2.push(to.st1, to.st2, to.step);q[tail++] = to;}swap(a[now], b[now]);}else {a[now] = getnew(a[now], b[now]);get_xy(to.st1, to.st2);to.step = cur.step+1;int temp = ha1.isin(to.st1, to.st2);if(temp >= 0)  {ok = 1;ans = min(ans, temp+to.step);continue;}if(ha2.isin(to.st1, to.st2) == -1 && to.step <= 10) {ha2.push(to.st1, to.st2, to.step);q[tail++] = to;}a[now] = getnew(a[now], b[now]);}swap(a[now], a[then]);swap(b[now], b[then]);if(ok)  break;}if(ok)  break;}}if(ans > 30)  return -1;return ans;
}int main() {int i, x, n, m;while(scanf("%d%d", &m, &n) != -1 && n) {int go = 0, st1 = 0, st2 = 0;char ch[2];for(i = 1;i <= 9; i++) {scanf("%s", ch);if(ch[0] == 'W') x = 1;else if(ch[0] == 'R')    x = 2;else if(ch[0] == 'B')    x = 3;else    x = 4;go = go*10 + x;if(i == (n-1)*3 + m) {st1 = st1*10+4;st2 = st2*10+4;}else  {st1 = st1*10+1;st2 = st2*10+2;}}if(st1 == go) {puts("0"); continue;}printf("%d\n", bfs(st1, st2, go));}return 0;
}

转载于:https://www.cnblogs.com/pangblog/p/3239133.html

poj 3131 Cubic Eight-Puzzle 双向广搜 Hash判重相关推荐

  1. POJ 1915(双向广搜)

    应该是双向广搜的简单题,虽然写了很久.双向:简而言之就是从起点(正向搜索)和终点(逆向搜索)同时开始搜索,当两个搜索产生的一个子状态相同时就结束搜索. 通常有两种实现方法: 1.用一个队列来储存子状态 ...

  2. 双向广搜(DBFS)

    双向广搜很早之前就像学习,但蒟蒻这道今天才会写(汗...) ---------------------------------------------------------------------- ...

  3. POJ 3131 Cubic Eight-Puzzle

    题意: 给你八个正方体,放于九宫格内,每个正方体相对面同色.每次可以将一个正方体翻滚到相邻空位,求使从高处向下看为给定的目标状态的最小移动次数.如果30步内不能到达判定无解. 题解: 三维八数码问题, ...

  4. 【图论专题】BFS中的双向广搜 和 A-star

    双向广搜 AcWing 190. 字串变换 #include <cstring> #include <iostream> #include <algorithm> ...

  5. 算法提高课-搜索-双向广搜 AcWing 190. 字串变换:bfs、双向bfs、queue和unordered_map

    题目分析 来源:acwing 分析: 双向广搜主要用在最小步数模型(也称状态图模型)里面,这里整个状态空间一般是指数级别的,用双向广搜可以极大地提高运行效率. 双向广搜,顾名思义,就是从起点和终点都进 ...

  6. 双向广搜 8数码问题

     转载自:http://blog.sina.com.cn/s/blog_8627bf080100ticx.html  Eight 题目链接:http://acm.hdu.edu.cn/showprob ...

  7. 万圣节后的早晨九数码游戏——双向广搜

    https://www.luogu.org/problemnew/show/P1778 https://www.luogu.org/problemnew/show/P2578 双向广搜. 有固定起点终 ...

  8. 双向广搜-HDU1401 Solitaire

    文章目录 双向广搜 例题 题意 分析 代码 小结 双向广搜 什么是双向广搜? 如果把bfs想象成在平静的池塘丢一颗石头,激起的波浪一层层扩散到整个空间直到到达目标,就得到起点到终点的最优路径.那么双向 ...

  9. 小游戏系列算法之五广度优先搜索,双向广搜,八数码,华容道

    前段时间在玩仙五前,遇上了蚩尤冢拼图这个小游戏. 其实就是八数码问题,一直想着如何才能用最少步数求解,于是就写了个程序. Q1:什么是八数码问题? A1:首先假定一个3*3的棋盘(如上图),分别有1, ...

最新文章

  1. svn git 导入本地文件到远程服务器 import
  2. BZOJ 2734 [HNOI2012]集合选数 (状压DP、时间复杂度分析)
  3. DICOM:标准内容概述
  4. clumsy模拟客户端网络差的场景的使用
  5. android 首页布局变换,Android XML布局与View之间的转换
  6. telnet入侵linux,教你入侵RedHatLinux
  7. Objective-C Fast Enumeration 的实现原理
  8. TNG-Hooks:有状态逻辑在标准函数中的重用和组合
  9. 文献阅读---普通狗牙根阳江基因组单倍型解析与基因组稳定性和匍匐性研究
  10. 健身教练教你跑步减肥的正确方法
  11. 打工就是 “演戏”,你可以认真,但别太当真
  12. ansible-playbook 远程启动程序ansible结束后程序也被关闭
  13. jdt eclipse_Eclipse JDT语言服务器项目
  14. 【总结】PHP常见面试题汇总(一)。。。
  15. 基于商品属性的相似度模型
  16. /deep/ 在谷歌浏览器89+版本失效问题解决
  17. 游戏音乐制作中需要使用那些软件?
  18. 暴力更改hex文件实现自动烧写stm32程序
  19. 91、储存物品的火灾危险性分类
  20. iOS 动态字体设置

热门文章

  1. java 自动类型_java类型自动转换
  2. agilebpm脑图_设计开发平台前端框架介绍 | AgileBPM 敏捷工作流开发平台—开源免费-基于 Activiti 工作流引擎、Flowable...
  3. HTML+CSS+JS实现 ❤️slicebox酷炫3d图片轮播切换❤️
  4. java aio socket_java核心学习(三十三) 网络编程---AIO实现异步Socket通信
  5. flash一个按钮控制动画_PLC三组灯用一个按钮控制
  6. mysql数据库里的表格_mysql数据库中表记录的玩法
  7. Java 输出当前目录
  8. java反编译工具_Java开发必会的反编译知识(附支持对Lambda进行反编译的工具)...
  9. 中国大学慕课python答案第七章_中国大学慕课mooc用Python玩转数据章节答案
  10. 自动驾驶芯片_自动驾驶芯片“争夺战”