Eight II

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 130000/65536 K (Java/Others)
Total Submission(s): 4103    Accepted Submission(s): 878


Problem Description
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

题目传送门

题目很好理解,就是个华容道的游戏,唯一要注意的就是要输出最短路径,长度相同时字典序要最小。

这道题和hdu1430方法一样,只不过1430是一次bfs+康托展开保存所有状态,而这个起点有九种,所以只要九次bfs就可以了,另外路径不能直接暴力保存,我是用了ans[x][e]来表示起点为x,走到康托值为e的操作字符,再用一个pre[x][e]来表示这个操作的前一个的康托值。另外这道题卡时间卡了一个减枝,就是如果前一步是u,那这一步就不需要d了,其他方向也一样,另外再赞一下这种把函数写在结构体里面的方法,真是太好用了!!

对了,还有由于每次输入的起点不一样,还有其他数字的位子也不一样,所以要用一个p来保存x的位置,(bfs过程中也要用p来表示x到哪里了,并且记得更新),然后用一个re[]数组来表示出了x以外的其他数字的对应关系,然后就可以了。

建议先做一下hdu1430,这是1430的题解。点击打开链接

上代码。

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=362880+10;
int fact[10]= {1,1,2,6,24,120,720,5040,40320,362880};
struct node {
char arr[10];
int val;
int p;
string step;
void contor() {
val=0;
for(int i=0; i<9; i++) {
int t=0;
for(int j=i+1; j<9; j++) {
if(arr[j]<arr[i])t++;
}
val+=t*fact[9-i-1];
}
val++;
}
void change_d(int x) {
char temp=arr[x];
arr[x]=arr[x+3];
arr[x+3]=temp;
p=x+3;
step+='d';
}
void change_l(int x) {
p=x-1;
char temp=arr[x];
arr[x]=arr[x-1];
arr[x-1]=temp;
step+='l';
}
void change_r(int x) {
p=x+1;
char temp=arr[x];
arr[x]=arr[x+1];
arr[x+1]=temp;
step+='r';
}
void change_u(int x) {
p=x-3;
char temp=arr[x];
arr[x]=arr[x-3];
arr[x-3]=temp;
step+='u';
}
node() {}
node(char *s) {
int i,j;
for(i = 0; i<strlen(s); i++) {
arr[i] = s[i];
}
}
};
int vis[N];
int pre[9][N];
char ans[9][N];
char re[10];
node s,t;
void bfs(int x) {
memset(pre[x],-1,sizeof(pre[x]));
memset(vis,0,sizeof(vis));
s.contor();
s.p=x;
queue<node>q;
vis[s.val]=1;
q.push(s);
node now,v;
while(!q.empty()) {
now=q.front();
q.pop();
v=now;
int e=v.val;
int len=v.step.length();
//d
if(v.p<6&&ans[x][e]!='u') {
v.change_d(v.p);
v.contor();
if(!vis[v.val]) {
vis[v.val]=1;
ans[x][v.val]='d';
pre[x][v.val]=e;
q.push(v);
}
}
//l
v=now;
if(v.p!=0&&v.p!=3&&v.p!=6&&ans[x][e]!='r') {
v.change_l(v.p);
v.contor();
if(!vis[v.val]) {
vis[v.val]=1;
ans[x][v.val]='l';
pre[x][v.val]=e;
q.push(v);
}
} //r
v=now;
if(v.p!=2&&v.p!=5&&v.p!=8&&ans[x][e]!='l') {
v.change_r(v.p);
v.contor();
if(!vis[v.val]) {
vis[v.val]=1;
ans[x][v.val]='r';
pre[x][v.val]=e;
q.push(v);
}
}
//u
v=now;
if(v.p>2&&ans[x][e]!='d') {
v.change_u(v.p);
v.contor();
if(!vis[v.val]) {
vis[v.val]=1;
ans[x][v.val]='u';
pre[x][v.val]=e;
q.push(v);
}
}
}
}
int main() {
s = node("X12345678");
bfs(0);
s = node("1X2345678");
bfs(1);
s = node("12X345678");
bfs(2);
s = node("123X45678");
bfs(3);
s = node("1234X5678");
bfs(4);
s = node("12345X678");
bfs(5);
s = node("123456X78");
bfs(6);
s = node("1234567X8");
bfs(7);
s = node("12345678X");
bfs(8);
char ss[10];
int T;
cin>>T;
int cas=1;
while(T--) {
scanf("%s",ss);
int p;
for(int i=0,j=0; i<9; i++) {
if(ss[i]=='X'){
p=i;
}else{
re[ss[i]-'0']=++j; //记住 是j
}
}
scanf("%s",ss);
for(int i=0; i<9; i++) {
if(ss[i]!='X')
t.arr[i]=re[ss[i]-'0'];
else t.arr[i]='X';
}
t.contor();
int sum=t.val;
string aa;
aa="";
while(sum!=-1){
aa+=ans[p][sum];
sum=pre[p][sum];
}
printf("Case %d: %d\n",cas++,aa.size()-1);//为什么要-1呢?因为第一种状态是空字符,不是路径
for(int i=aa.size()-2;i>=0;i--)
printf("%c",aa[i]);
printf("\n");
}
}

hdu3567 八数码2(康托展开+多次bfs+预处理)的更多相关文章

  1. HDU 1043 Eight (BFS&#183;八数码&#183;康托展开)

    题意  输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数  即这个排列在全部排列中的字典序  然后就是基础的BFS了 #include <bits/stdc++.h ...

  2. hdu1043Eight (经典的八数码)(康托展开+BFS)

    建议先学会用康托展开:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description The 15-puzzle ...

  3. 八数码问题(一) 暴力BFS + STL

    八数码问题是一个经典的人工智能问题.具体问题不累述了. 思路:由于存在多组测试数据,可以考虑“打表法“.所谓打表法,即枚举所有的初始情况,记录其到达终点的路径.而在这个题目中,顺序打表会调用很多次BF ...

  4. hdu3567 八数码(搜索)--预处理

    题意:为你两个状态,求a到b 的最小路径,要求字典序最小. 思路: 最开始想的是目标状态是变化的,所以打表应该不行,然后直接上A*,但是TLE了- -(瞬间无语) 然后看了下别人的思路,预处理出9个状 ...

  5. Aizu0121 Seven Puzzle(bfs+康托展开)

    https://vjudge.net/problem/Aizu-0121 比八数码要水的多,bfs. 但是做的时候我把康托展开记错了,wa了好几次. 附上康托展开博客详解:https://blog.c ...

  6. HDU1430;魔板(BFS+康托展开)

    传送门 题意 给出初始序列与终止序列,给出三种操作,问最少经过几次操作能使初始->终止,输出操作(字典序最小) 分析 字符串只有8个字符,使用康托展开. 1.BFS将所有序列从"123 ...

  7. 双向广搜+hash+康托展开 codevs 1225 八数码难题

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

  8. hdu-1043(八数码+bfs打表+康托展开)

    参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html 康托展开:https://blog.csdn.net/wbin233/article/deta ...

  9. HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

随机推荐

  1. Struts2框架06 ValueStack

    原文地址:点击前往 1 什么是ValueStack 称为值栈,Struts提供的共享数据的数据结构 2 为什么要使用ValueStack 从控制器向浏览器传递数据 存储与请求相关的对象信息(sessi ...

  2. SQl Server 函数篇 数学函数,字符串函数,转换函数,时间日期函数

    数据库中的函数和c#中的函数很相似 按顺序来, 这里价格特别的 print  可以再消息栏里打印东西 数学函数 ceiling()  取上限   不在乎小数点后面有多大,直接忽略 floor()   ...

  3. iOS 本地加载js文件

    #import "RootViewController.h" @interface RootViewController ()<UIWebViewDelegate> @ ...

  4. Configuration File (php.ini) Path Loaded Configuration File 都有加载php.ini文件,有什么不同的地方?

    Configuration File (php.ini) Path /usr/local/php7/etc      这个目录下面也有php.ini文件(如果在编译./configure -with- ...

  5. ZROI2018提高day6t1

    传送门 分析 我们发现这个四元组可以分解成一个逆序对拼上一个顺序对,这个线段树搞搞然后乘一下就可以求出来了,但是我们发现可能有(a,b)为逆序对且(b,c)为顺序对的情况,所以要进行容斥,我们只需要枚 ...

  6. CF 1025C Plasticine zebra

    昨晚忘记判只有一个字符的情况fst了呜呜呜 挺有趣的题,昨晚连刚带猜弄出结论 考虑答案的取值,最优答案可能是一个后缀,或者是一个前缀,或者是一个后缀加上前缀 那么翻转之后最优答案的可选值就有了1的前缀 ...

  7. Bootstrap 的 Collapse

    一.简介 Collapse 插件为 HTML 标签提供折叠.展开行为,依赖 transition.js(bootstrap.js 文件中已包含). 二.实现机制 实现 Collapse 效果需要: 一 ...

  8. [转]CMD命令提示符窗口中的快捷键、小技巧和常用命令

    转至:https://wenku.baidu.com/view/d5d2b7ca360cba1aa811dac6.html 快捷键:  F1:按F1一次,命令提示符向后切换到已经执行过的命令字符.如果 ...

  9. postgre-sql语法

    //客户端查询 public void pgsearchclient(HttpContext context, string starttime, string endtime, int page, ...

  10. DjVu、PDF中的隐藏文本

    作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.06.11 目录一.背景二.DjVu中的隐藏文本三.PDF中的隐藏文本 一.背景 目前对于扫描电子文档,网上比较流行 ...