题目描述:

Eight-puzzle, which is also called “Nine grids”, comes from an old game
In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see, there is a blank grid which can be represented as an ‘X’. Tiles in grids having a common edge with the blank grid can be moved into that blank grid. This operation leads to an exchange of ‘X’ with one tile.
We use the symbol ‘r’ to represent exchanging ‘X’ with the tile on its right side, and ‘l’ for the left side, ‘u’ for the one above it, ‘d’ for the one below it.

A state of the board can be represented by a string S using the rule showed below.

The problem is to operate an operation list of ‘r’, ‘u’, ‘l’, ‘d’ to turn the state of the board from state A to state B. You are required to find the result which meets the following constrains:
1. It is of minimum length among all possible solutions.
2. It is the lexicographically smallest one of all solutions of minimum length.

Input

The first line is T (T <= 200), which means the number of test cases of this problem.
The input of each test case consists of two lines with state A occupying the first line and state B on the second line.
It is guaranteed that there is an available solution from state A to B.

Output

For each test case two lines are expected.
The first line is in the format of “Case x: d”, in which x is the case number counted from one, d is the minimum length of operation list you need to turn A to B.
S is the operation list meeting the constraints and it should be showed on the second line.

Sample Input

2
12X453786
12345678X
564178X23
7568X4123

Sample Output

Case 1: 2
dd
Case 2: 8
urrulldr

方法一: 双向bfs,枚举最短路更新最小字典序

#include<stdio.h>
#include<iostream>
#include<string>
#include<queue>
#include<math.h>
#include<string.h>using namespace std;typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 362890;
const int inf = 0x3f3f3f3f;
const double Pi = acos(-1.0);
const LL INF = 0x3f3f3f3f3f3f3f3f;
const char g[] = "dlru";
const int dir[4][2] = {1, 0, 0, -1, 0, 1, -1, 0};
const int fac[10]={1,1,2,6,24,120,720,5040,40320,362880};
const LL pow4[]={1,4,16,64,256,1024,4096,16384,65536,262144,1048576,4194304,16777216,67108864,268435456,1073741824,4294967296,17179869184,68719476736,274877906944,1099511627776,4398046511104,17592186044416,70368744177664,281474976710656,1125899906842624,4503599627370496,18014398509481984,72057594037927936,288230376151711744,1152921504606846976,4611686018427387904};template<class T, class F> inline void mem(T a,F b, int c) {for(int i=0;i<=c;++i)a[i]=b;}
template<class T> inline void read(T &x,T xk=10) { // xk 为进制char ch = getchar(); T f = 1, t = 0.1;for(x=0; ch>'9'||ch<'0'; ch=getchar()) if(ch=='-')f=-1;for(;ch<='9'&&ch>='0';ch=getchar())x=x*xk+ch-'0';if(ch=='.') for(ch=getchar();ch<='9'&&ch>='0';ch=getchar(),t*=0.1)x+=t*(ch-'0');x*=f;
}struct node{char str[9];int Hash;int flag;int step;int x, y;LL  path;void cantor() {Hash = 0;for(int i = 0; i < 9; ++ i) {for(int j = i + 1; j < 9; ++ j) {if (str[i] > str[j]) Hash += fac[8-i];}}}
};LL path[2][maxn];
int visit[2][maxn];string get_path(int flat, int Hash) { string res;LL m = path[flat][Hash];for(int i = visit[flat][Hash]; i >= 1; -- i) {res += g[m / pow4[i-1]];m %= pow4[i-1];}return res;
} void bfs(node n1, node n2){memset(visit, -1, sizeof(visit));queue<node> q;q.push(n1); visit[0][n1.Hash] = 0;q.push(n2); visit[1][n2.Hash] = 0;string cnt;if (n1.Hash == n2.Hash) {cout << 0 << endl;cout << endl;return ;}while(!q.empty()) {node temp = q.front();q.pop();for(int i = 0; i < 4; ++ i) {node c = temp;c.x = temp.x + dir[i][0];c.y = temp.y + dir[i][1];if (c.x >= 0 && c.x < 3 && c.y >= 0 && c.y < 3) {++ c.step; if (c.flag) c.path = c.path + (3-i) * pow4[temp.step];else c.path = c.path * 4 + i;swap(c.str[c.x*3+c.y], c.str[temp.x*3+temp.y]);c.cantor();if (visit[c.flag][c.Hash] == -1) { // 新点入队visit[c.flag][c.Hash] = c.step;path[c.flag][c.Hash] = c.path;q.push(c);}else { // 更新最短路径if (visit[c.flag][c.Hash] < c.step) continue;if (path[c.flag][c.Hash] < c.path) continue;path[c.flag][c.Hash] = c.path;q.push(c);}if (visit[c.flag^1][c.Hash] != -1) { // 在同意最短路下找到最小字典序 string res = get_path(0, c.Hash) + get_path(1, c.Hash);if (cnt.empty()) cnt = res;if (cnt.size() < res.size()) {cout << cnt.size() << endl;cout << cnt << endl;return ;}cnt = min(cnt, res);}    }}}
}int main() {int T; read(T);for(int k = 1; k <= T; ++ k) {node st, en;scanf("%s%s", st.str, en.str);for(int i = 0; i < 9; ++ i) {if (st.str[i] == 'X') {st.str[i] = '0';st.x = i / 3;st.y = i % 3; st.flag = 0;st.step = 0;st.path = 0;st.cantor();}if (en.str[i] == 'X') {en.str[i] = '0';en.x = i / 3;en.y = i % 3;en.flag = 1;en.step = 0;en.path = 0;en.cantor();}}cout << "Case " << k << ": ";bfs(st, en);}return 0;
}

方法二: 单向bfs打表,把初始状态hash成有序状态,单向打表

#include<stdio.h>
#include<iostream>
#include<string>
#include<queue>
#include<math.h>
#include<string.h>using namespace std;typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 362890;
const int inf = 0x3f3f3f3f;
const double Pi = acos(-1.0);
const LL INF = 0x3f3f3f3f3f3f3f3f;
const char g[] = "dlru";
const int dir[4][2] = {1, 0, 0, -1, 0, 1, -1, 0};
const int fac[10]={1,1,2,6,24,120,720,5040,40320,362880};
const LL pow4[]={1,4,16,64,256,1024,4096,16384,65536,262144,1048576,4194304,16777216,67108864,268435456,1073741824,4294967296,17179869184,68719476736,274877906944,1099511627776,4398046511104,17592186044416,70368744177664,281474976710656,1125899906842624,4503599627370496,18014398509481984,72057594037927936,288230376151711744,1152921504606846976,4611686018427387904};
const char Map[9][10] = {"012345678", "102345678", "120345678", "123045678", "123405678", "123450678", "123456078", "123456708", "123456780"};template<class T, class F> inline void mem(T a,F b, int c) {for(int i=0;i<=c;++i)a[i]=b;}
template<class T> inline void read(T &x,T xk=10) { // xk 为进制char ch = getchar(); T f = 1, t = 0.1;for(x=0; ch>'9'||ch<'0'; ch=getchar()) if(ch=='-')f=-1;for(;ch<='9'&&ch>='0';ch=getchar())x=x*xk+ch-'0';if(ch=='.') for(ch=getchar();ch<='9'&&ch>='0';ch=getchar(),t*=0.1)x+=t*(ch-'0');x*=f;
}struct node {char str[9];int x, y;int Hash;void cantor() {Hash = 0;for(int i = 0; i < 9; ++ i) {for(int j = i + 1; j < 9; ++ j) {if (str[i] > str[j]) Hash += fac[8-i];}}}
};int visit[9][maxn];
char path[9][maxn];void bfs(int x, node a) {queue<node> q;q.push(a);visit[x][a.Hash] = -2;while(!q.empty()) {node temp = q.front();q.pop();for(int i = 0; i < 4; ++ i) {node c = temp;c.x = temp.x + dir[i][0];c.y = temp.y + dir[i][1];if (c.x >= 0 && c.x < 3 && c.y >= 0 && c.y < 3) {swap(c.str[c.x*3+c.y], c.str[temp.x*3+temp.y]);c.cantor();if (visit[x][c.Hash] != -1) continue;visit[x][c.Hash] = temp.Hash;path[x][c.Hash] = g[i];q.push(c);}}}
}int main() {memset(visit, -1, sizeof(visit));int A[9];for(int i = 0; i < 9; ++ i) {node a;for(int j = 0; j < 9; ++ j) a.str[j] = Map[i][j];a.x = i / 3;a.y = i % 3;a.cantor();A[i] = a.Hash;bfs(i, a);}int T; read(T);for(int K = 1; K <= T; ++ K) {node st, en;scanf("%s%s", st.str, en.str);int tot = 0, b[9], k;for(int i = 0; i < 9; ++ i) {if (st.str[i] == 'X') k = i;else b[st.str[i] - '0'] = ++ tot;}for(int i = 0; i < 9; ++ i) {if (en.str[i] == 'X') en.str[i] = '0';else en.str[i] = b[en.str[i] - '0'] + '0';if (i == 8) en.cantor();}char res[100];int ans = en.Hash, cnt = 0;while(visit[k][ans] != -2) {res[++cnt] = path[k][ans];ans = visit[k][ans];}printf("Case %d: %d\n", K, cnt);for(int i = cnt; i >= 1; -- i) {printf("%c",res[i]);}printf("\n");}return 0;
}

HDU - 3567~~Eight II相关推荐

  1. Eight II HDU - 3567

    Eight II HDU - 3567 题意:给定方阵A与B,要求通过交换X格子与其相邻方格位置的方式,使得A与B相同.输出具体操作步骤.要求答案是步骤最少的答案,若有多个,还要是字典序最小的答案.

  2. HDU - 5919 Sequence II——主席树+区间种类++逆序建树

    [题目描述] HDU - 5919 Sequence II [题目分析] 题目给定一个数组,每次查询一个区间,找出区间内不同数字的个数x,然后输出按出现顺序第x/2向上取整个数字的位置. 按照要求,我 ...

  3. HDU 5919 Sequence II 主席树

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5919 Sequence II Time Limit: 9000/4500 MS (Java/Othe ...

  4. hdu 1430+hdu 3567(预处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路:由于只是8种颜色,所以标号就无所谓了,对起始状态重新修改标号为 12345678,对目标状 ...

  5. HDU 3081Marriage Match II(二分法+并检查集合+网络流量的最大流量)

    职务地址:http://acm.hdu.edu.cn/showproblem.php? pid=3081 有一段时间没写最大流的题了,这题建图竟然想了好长时间... 刚開始是按着终于的最大流即是做多轮 ...

  6. hdu 5233 Gunner II

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5233  简单题,stl水之... 1 #include<algorithm> 2 #inc ...

  7. hdu 4043 FXTZ II [ 概率 + Java大数]

    传送门 FXTZ II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  8. HDU - 5919 Sequence II(主席树+思维)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a ,再给出 m 次询问,每次询问给出一个区间 [ l , r ] ,问区间 [ l , r ] 内首次出现的数字的位置的中位数 题目分析:题 ...

  9. HDU - 5919 Sequence II

    题意: 给定长度为n的序列和q次询问.每次询问给出一个区间(L,R),求出区间内每个数第一次出现位置的中位数,强制在线. 题解: 用主席树从右向左的插入点.对于当前点i,如果a[i]出现过,则把原位置 ...

最新文章

  1. python免费视频-Python免费视频教程
  2. 翟树卿:如何让数据挖掘助力精准化营销
  3. 系统设计:性能指标、伸缩性、扩展性、可用性、安全性
  4. crt脚本 js 在_crt脚本 js 在_使用SecureCRT自带的脚本录制功能。
  5. mysqld进程 ut_delay 占用率过高
  6. 系统启动 之 Linux系统启动概述(2)
  7. sql IDENTITY(函数)
  8. 九章算术卷第一 方田
  9. 7限制cpu使用_macOS限制CPU或进程使用率
  10. 一个在ns3平台基于UDP协议实现的拥塞控制仿真框架
  11. 一起走过的日子.大学本科和同学拍的DV,还有全家福~
  12. 文本转语音-微软Azure-一步一步教你从注册到使用
  13. 分布式:分布式系统设计策略。
  14. 关于unity数值资源序列化后在windows和android平台的本地读取
  15. 计算机修改users用户名,笔记本电脑更改用户名_笔记本电脑更改user
  16. python人机对话存在的问题_如何适应人机对话要点及情景问题
  17. [P3518]strongbox
  18. 徐无忌MySQL笔记:案例实战:如何实现MySQL数据库的读写分离?
  19. ImageJ如何数值化色谱图
  20. JDBC链接数据库的步骤

热门文章

  1. AI 时代的学习方式: 和文档对话
  2. 百度财报解读:营收持平净利增,“文心一言”站C位
  3. 唐伯虎热衷于娱乐活动李舟楫的博客新浪博客
  4. Echarts图实现折线图根据自定义标准线,超过标准值是一种颜色低于标准值是一种颜色
  5. iphone 白苹果问题_苹果公司的特别活动:新款iPhone等
  6. Steve jobs
  7. ### CausDriver com.mysql.jdbc.Driver claims to not accept jdbcUrl, mysql:jdbc://localhost:3306/mysql
  8. 职场10个受欢迎的英文名
  9. 设计模式--第七章 克隆模式
  10. Python函数(函数定义、函数调用)用法详解