题目连接:https://vjudge.net/contest/353606#problem/B

参考文章:https://blog.csdn.net/laaahu/article/details/96648344

思路:

广搜,记录路径,因为最多的交换次数不会太多,所以可以用int类型的4进制数记录路径;因为要求字典序最小,所以走得方向是dlru,当每次找到合法的路径时判断是否是字典序最小的路径,因为是双向bfs,每次判断当前路径是否是字典序最小的,不断更新就好了。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 9;
const int MAXN = 4e5 + 10;
const int inf = 1e9+10;
char s1[N + 5], s2[N + 5];
int min_step, vis[2][MAXN],tp[120];
ll pre[2][MAXN], pp[120];
struct Node {int id, loc, b[N], stu, num;ll path;
};
char op[5] = "dlru";
string rs;
int dx[4] = {1, 0, 0, -1};
int dy[4] = {0, -1, 1, 0};
int cantor(int aa[]) {int ans = 0;for(int i = 0; i < 9; i++) {int res = 0, m = 1, c = 1;for(int j = i + 1; j < 9; j++) {if(aa[j] < aa[i])res++;m *= c;c++;}ans += res * m;}return ans + 1;
}
string get_path(ll x,int bj,int k)
{int tot = 0;for(int i=1;i<=vis[bj][k];i++){tp[++tot] = x%4; x/=4;}string ss = "";for(int i=tot;i>=1;i--){ss += op[ tp[i] ];}return ss;
}
void bfs() {memset(vis, -1, sizeof(vis));queue <Node> q;Node t1, t2;for(int i = 0; i < 9; i++) {if(s1[i] == 'X')t1.b[i] = 9, t1.loc = i;elset1.b[i] = s1[i] - '0';if(s2[i] == 'X')t2.b[i] = 9, t2.loc = i;elset2.b[i] = s2[i] - '0';}t1.id = 0;t1.stu = cantor(t1.b);t1.path = 0;vis[0][t1.stu] = 0;t1.num = 0;t2.id = 1;t2.stu = cantor(t2.b);t2.path = 0;vis[1][t2.stu] = 0;t2.num = 0;q.push(t1);q.push(t2);while(!q.empty()) {t1 = q.front();q.pop();ll tmp;int x = t1.loc / 3, y = t1.loc % 3, id = t1.id;//printf("x = %d,y = %d,id = %d\n",x,y,id);for(int i = 0; i < 4; i++) {int tx = x + dx[i];int ty = y + dy[i];if(0 <= tx && tx < 3 && 0 <= ty && ty < 3) {t2 = t1;t2.b[x * 3 + y] = t2.b[tx * 3 + ty];t2.b[tx * 3 + ty] = 9;//for(int j=0;j<9;j++) printf("%d",t2.b[j]); printf("\n");t2.loc = tx * 3 + ty;t2.stu = cantor(t2.b);t2.num = t1.num + 1;if(vis[id][t2.stu] == -1) {vis[id][t2.stu] = t1.num + 1;if(id == 1)pre[id][t2.stu] = (3 - i) * pp[t1.num] + t1.path;elsepre[id][t2.stu] = t1.path * 4 + i;} else {if(t2.num > vis[id][t2.stu])continue;else {if(id == 1)tmp = (3 - i) * pp[t1.num] + t1.path;elsetmp = t1.path * 4 + i;if(tmp < pre[id][t2.stu]) {pre[id][t2.stu] = tmp;}}}t2.path = pre[id][t2.stu];if(vis[id ^ 1][t2.stu] != -1) {string ss = get_path(pre[0][t2.stu], 0, t2.stu) + get_path(pre[1][t2.stu], 1, t2.stu);int len = ss.length();if(len < min_step) {min_step = len;rs = ss;} else if(len > min_step) {cout << min_step << endl;cout << rs << endl;return ;} else {if(rs.compare(ss) > 0)rs = ss;}}q.push(t2);}}}
}
int main(void) {pp[0] = 1;for(int i = 1; i <= 33; i++)pp[i] = pp[i - 1] * 4;int T;scanf("%d", &T);for(int pt = 1; pt <= T; pt++) {scanf("%s%s", s1, s2);bool fg = false;for(int i = 0; i < 9; i++) {if(s1[i] != s2[i])fg = true;}//printf("s1 = %s,s2 = %s\n",s1,s2);if(fg == false) {printf("Case %d: 0\n\n", pt);continue;}min_step = inf;printf("Case %d: ", pt);bfs();}return 0;
}

hdu 3567(八码数 + 双向bfs)相关推荐

  1. 八码数-IDA*算法

    A是用在BFS上的 A=优先队列+估价函数 IDA是用在DFS上的 IDA=迭代加深+估价函数 一般来说IDA优于A主要在A的BSF内存的需求,且不需要对启发值排序.我是更喜欢用IDA*. IDA*相 ...

  2. 关于八码数问题有解与无解的证明

    转载自[水木清华BBS精华区]:http://www.cnw3.org/smth/AI/5/8/00000001.htm 发信人: YourMajesty (花痴~~~~小魔男), 信区: AI 标 ...

  3. 八码数 · 哈希+BFS

    //本代码还未ac#include <bits/stdc++.h> using namespace std; typedef long long ll; #define between(x ...

  4. HDU Problem - 3085 Nightmare Ⅱ(双向BFS)

    题目链接 Problem Description Last night, little erriyue had a horrible nightmare. He dreamed that he and ...

  5. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  6. python 八数码_python 处理八数码 双向BFS 拼图游戏 | 学步园

    我的代码一开始是单向的BFS 然后很慢,5分钟? 参照别人的代码后,改用双向BFS 很快 拼图问题 == 八数码问题 从开始状态start,进行BFS 同时,从结束状态end,进行BFS 如果左图能够 ...

  7. C++解题报告:详解经典搜索难题——八数码问题( 双向BFS A* 求解)

    引言 AC这道八数码问题,你和楼教主就是兄弟了... 题目描述 在一个3*3的九宫格棋盘里,放有8个数码,数码的数字分别是1~8.棋盘中还有一个位置是空着的,用0表示.可以通过在九宫格里平移数码来改变 ...

  8. 专题训练二 搜索进阶 HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离)

    HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离) Problem Description Last night, little erriyue had a horrible ...

  9. HDU - 3085 Nightmare Ⅱ(双向bfs)

    题目链接:点击查看 题目大意:给出一个迷宫,一个男孩和一个女孩还有两只鬼,男孩每秒钟走3格,女孩每秒钟走1格,鬼每秒钟向四周分裂2格,问男孩和女孩能否在鬼占领迷宫之前汇合,能的话输出汇合时间,否则输出 ...

最新文章

  1. 「学习笔记-Linux」学习Shell Script
  2. 观点 | 李开复谈AI创业的“风口”和“泡沫”
  3. TReader高速文本浏览器 1.0 发布
  4. 使用Sysmon和Splunk探测网络环境中横向渗透
  5. 【论文解读】Graph Normalization (GN):为图神经网络学习一个有效的图归一化
  6. SpringBoot基础重难点
  7. django中collectstatic的使用(亲测)
  8. [LeetCode] NO.292 Nim Game
  9. javascript原型链中 this 的指向
  10. bzoj2111,P2606-[ZJOI2010]排列计数【Lucas,组合计数,dp】
  11. SQL SERVER7应用
  12. 初识C++之运算符重载
  13. 真假签到题(签到+打表)
  14. ToolsOh第8批收录
  15. Windows10禁用Adobe Creative Cloud开机自启动
  16. 蒙特卡罗模拟/蒙特卡罗方法
  17. c语言将love转换成小写love,介绍UDF,以及完成大小写的转换
  18. 永恒之蓝(MS17-010)
  19. 树莓派4B最新系统bullseye更换国内源方法
  20. 2019年最新网盘搜索引擎汇总

热门文章

  1. 数学与计算机学院迎新晚会,数青春年华,计未来梦想——数学系、计算机科学系举办2016级迎新晚会...
  2. 什么是期权?如何从概念上理解看涨期权/看跌期权?
  3. DP地狱训练 挤牛奶
  4. fmute hang_detect 与ARM 镜像
  5. html中什么是功能链接,链接是什么?(链接的意思与功能)
  6. 一名合格的管理者应具备哪些能力与素质?
  7. LatentFusion:End-to-End Differentiable Reconstruction and Rendering for Unseen Object Pose Estimatio
  8. 适用于Mac的16款3D打印机建模软件
  9. [P2600][ZJOI2008]瞭望塔(半平面交)
  10. 无领导小组讨论中常见的派别