魔板

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2921    Accepted Submission(s): 649

Problem Description
在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板。魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为:

1 2 3 4
8 7 6 5

对于魔板,可施加三种不同的操作,具体操作方法如下:

A: 上下两行互换,如上图可变换为状态87654321
B: 每行同时循环右移一格,如上图可变换为41236785
C: 中间4个方块顺时针旋转一格,如上图可变换为17245368

给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。

 
Input
每组测试数据包括两行,分别代表魔板的初态与目态。

 
Output
对每组测试数据输出满足题意的变换步骤。

 
Sample Input
12345678
17245368
12345678
82754631
 
Sample Output
C
AC

题目链接:HDU 1430

原来思路是就用康托展开映射然后每一次都从S搜索到T然而T了。

然后改为预处理,从12345678开始把其他状态全部搜完并记录,O(1)输出,但是由于一开始的S不一定是12345678,因此要用一个映射数组refl[]来记录S与12345678的关系,然后根据这个关于把T也转换成相对应的关系,之后还是WA很久,后来发现是第二种变化的后半部分循环反了(囧)……

按照A、B、C的顺序变化使得达到的某一状态都是最优解即长度最小的情况下字典序也最小(也可以用优先队列来实现就是速度慢了点),然后加了个没什么用的剪枝防止出现AA、BBBB、CCCC这样又变回原来状态的无意义操作。把康托展开写在结构体里简直方便的不行……

给一组测试数据

63728145
86372541

ACBBBCBBCBCBCABB

这组能过的话基本上就可以A了

代码:

#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=40320+10;
int fact[9]={1,1,2,6,24,120,720,5040,40320};
struct info
{
int arr[8];
int val;
string step;
void cantor()
{
val=0;
for (int i=0; i<8; ++i)
{
int k=0;
for (int j=i+1; j<8; ++j)
{
if(arr[j]<arr[i])
++k;
}
val+=k*fact[7-i];
}
}
void change_A()
{
reverse(arr,arr+8);
step+="A";
}
void change_B()
{
int temp=arr[3];
for (int i=3; i>0; --i)
arr[i]=arr[i-1];
arr[0]=temp; temp=arr[4];
for (int i=4; i<7; ++i)
arr[i]=arr[i+1];
arr[7]=temp;
step+="B";
}
void change_C()
{
int temp=arr[2];
arr[2]=arr[1];
arr[1]=arr[6];
arr[6]=arr[5];
arr[5]=temp;
step+="C";
}
};
info S,T;
char s[10];
int vis[N];
string ans[N];
int refl[10];
void bfs()
{
CLR(vis,0);
queue<info>Q;
vis[S.val]=1;
Q.push(S);
info now,v;
while (!Q.empty())
{
now=Q.front();
Q.pop();
int len=(int)now.step.length();
if(len<1||now.step[len-1]!='A')
{
v=now;
v.change_A();
v.cantor();
if(!vis[v.val])
{
vis[v.val]=1;
ans[v.val]=v.step;
Q.push(v);
}
}
if(len<3||now.step[len-1]!='B'||now.step[len-2]!='B'||now.step[len-3]!='B')
{
v=now;
v.change_B();
v.cantor();
if(!vis[v.val])
{
vis[v.val]=1;
ans[v.val]=v.step;
Q.push(v);
}
}
if(len<3||now.step[len-1]!='C'||now.step[len-2]!='C'||now.step[len-3]!='C')
{
v=now;
v.change_C();
v.cantor();
if(!vis[v.val])
{
vis[v.val]=1;
ans[v.val]=v.step;
Q.push(v);
}
}
}
}
int main(void)
{
int i;
for (i=0; i<8; ++i)
S.arr[i]=i+1;
S.cantor(); bfs(); while (~scanf("%s",s))
{
for (i=0; i<8; ++i)
refl[s[i]-'0'-1]=i+1; scanf("%s",s);
for (i=0; i<8; ++i)
T.arr[i]=refl[s[i]-'0'-1];
T.cantor(); printf("%s\n",ans[T.val].c_str());
}
return 0;
}

HDU 1430 魔板(康托展开+BFS+预处理)的更多相关文章

  1. hdu 1430 魔板 康托展开 + 很好的映射

    http://acm.hdu.edu.cn/showproblem.php?pid=1430 如果从start ---> end,每一次都bfs进行,那么就肯定会超时. 考虑到先把start映射 ...

  2. HDU - 1430 魔板 【BFS + 康托展开 + 哈希】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路 我刚开始 想到的 就是 康托展开 但是这个题目是 多组输入 即使用 康托展开 也是会T的 ...

  3. hdu.1430.魔板(bfs + 康托展开)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  4. HDU - 1430 魔板 (bfs预处理 + 康托)

    对于该题可以直接预处理初始状态[0, 1, 2, 3, 4, 5, 6, 7]所有可以到达的状态,保存到达的路径,直接打印答案即可. 关于此处的状态转换:假设有初始状态为2,3,4,5,0,6,7,1 ...

  5. HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   Special ...

  6. [HDU 1430] 魔板

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  7. hdu 1430 魔板 (BFS+预处理)

    Problem - 1430 跟八数码相似的一题搜索题.做法可以是双向BFS或者预处理从"12345678"开始可以到达的所有状态,然后等价转换过去直接回溯路径即可. 代码如下: ...

  8. hdu1430 魔板(康拓展开 bfs预处理)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  9. HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3

    http://acm.hdu.edu.cn/showproblem.php?pid=3567 相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过, ...

随机推荐

  1. WIN7实现多人远程一台电脑

    今天查了查网,发现有人说,WIN7可以实现多人远程一台电脑,于是乎我就试了试, 在工作办公室里的局域网里试了试,嘿,成功了,愿与大家分享一下,呵呵! 方法一: 多用户早就能破解了 方法如下:用UE打开 ...

  2. SQL 代码创建表格以及CRUD

    create table <表名>( <列名> <数据类型及长度> [not null], <列名> <数据类型及长度>, ... < ...

  3. 记VS2013并行编译导致出错的解决过程

    接前一篇,电脑换了新的,系统是64bit的win8系统,先安装了SQLServer2012,再安装VS2010旗舰版,Stop!为什么还是2010?因为2010太经典了,以至于公司的项目还在用它写项目 ...

  4. php 解决和避免form表单重复提交的方法

    在提交表单的时候,可能遇到网速等导致页面突然加载变慢,用户重复地点击提交按钮,将在数据库产生多条数据,导致不可控情况. 比如下面的情况就会导致表单重复提交: 点击提交按钮两次. 点击刷新按钮. 使用浏 ...

  5. poj 1159 dp回文串

    题意:添加最少的字符使之成为回文串 #include<cstdio> #include<iostream> #include<algorithm> #include ...

  6. matlab参数查询

    nargout nargout的作用是在matlab中定义一个函数时, 在函数体内部, nargout指出了输出参数的个数(nargin指出了输入参数的个数). 特别是在利用了可变参数列表的函数中, ...

  7. editplus利用正则表达式快速定位

    例如我要找到user_jj表保存数据的语句 做法:editplus选择正则表达式输入 user_jj.*save 就可以定位到:M('user_jj')->where(array('tgbz_i ...

  8. awk命令

    awk 手册   原文 Table of Contents 1. awk简介 2. awk命令格式和选项 2.1. awk的语法有两种形式 2.2. 命令选项 3. 模式和操作 3.1. 模式 3.2 ...

  9. C. Graph and String

    二分图染色 b点跟除自身外所有的点连接,共n-1个,首先把连接n-1个的点全部设为b点,其它点任意一点设为a,与a相连的都是a点,剩余为c点.最后验证是否成立. 验证条件为,所有连接的点之间的差值的绝 ...

  10. mac OS X操作--快捷键