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

由于刚做完八数码问题,再来做这题,认为非常简单。可是用bfs超时(原因是多组数据,太多的数据将程序拖到超时),用dbfs就一直wa(原来是反向的搜索不能保证后半段的字典序最小,只能保证后半段的逆序的字典序最小),所以就得不到正确结果。

百度了一下,原来使用映射+bfs预处理的方法解决的,这样,再多组数据也不怕了。

将任意的初始状态映射为12345678,在这个过程中得到一个映射函数,目标状态根据这个映射函数,映射为相应的目标状态。(这样子能得到正确答案的原因是,魔板的变换,其实只是位置的变换,数字只是用来标记位置的而已,通过同一种映射关系将初始和目标状态的标记同时该改变,所以仍然能得到正确答案)

那么所有的数据,都能转化为初始状态为12345678的搜索,那么只要一遍bfs搜索出12345678所有能到达的状态,并记录步骤即可。

 #include <stdio.h>
#include <string.h>
#include <queue>
#include <string>
#include <iostream>
using namespace std;
char st[],ed[];
int vis[];
string ans[];
int fac[] = {,,,,,,,,};
int getHash(char *str)//康托展开
{
int i,j,hash = ,cnt;
for(i=; i<; ++i)
{
cnt = ;
for(j=i+; j<; ++j)
if(str[j]<str[i])
cnt++;
hash += cnt * fac[-i-];
}
return hash;
}
struct node
{
char str[];
};
int d[][] = {{,,,,,,,},{,,,,,,,},{,,,,,,,}};
char change[]; void bfs()
{
queue<node> q;
node cur,tmp;
int i,j;
for(i=; i<; ++i)
cur.str[i] = i + '';
int hash = getHash(cur.str);
q.push(cur);
vis[hash] = true;
q.push(cur);
while(!q.empty())
{
cur = q.front(); q.pop();
int pHash = getHash(cur.str);
for(i=; i<; ++i)
{
for(j=; j<; ++j)
tmp.str[j] = cur.str[d[i][j]];
hash = getHash(tmp.str);
if(vis[hash]) continue;
vis[hash] = true;
ans[hash] = ans[pHash] + (char)('A' + i);
q.push(tmp);
}
}
} int main()
{
bfs();
int i;
while(scanf("%s%s",st,ed)!=EOF)
{
for(i=; i<; ++i)
change[st[i]-''] = i+'';//得到映射函数
for(i=; i<; ++i)
ed[i] = change[ed[i]-''];//根据映射函数改变目标状态
int hash = getHash(ed);
cout<<ans[hash]<<endl;
}
return ;
}

hdu1430魔板的更多相关文章

  1. hdu1430魔板(BFS+康托展开)

    做这题先看:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description 在魔方风靡全球之后不久,Rubik先 ...

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

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

  3. hdu-1430 魔板 康拓展开+映射优化

    给定三种操作,将排列A转化为排列B,求最少步骤. 这种题目可以只跑一次bfs,比如只跑"12345678",那么如果遇到"23456781"->某个字符串 ...

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

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

  5. ACM-康托展开+预处理BFS之魔板——hdu1430

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

  6. Sicily 1051: 魔板(BFS+排重)

    相对1150题来说,这道题的N可能超过10,所以需要进行排重,即相同状态的魔板不要重复压倒队列里,这里我用map储存操作过的状态,也可以用康托编码来储存状态,这样时间缩短为0.03秒.关于康托展开可以 ...

  7. Sicily 1150: 简单魔板(BFS)

    此题可以使用BFS进行解答,使用8位的十进制数来储存魔板的状态,用BFS进行搜索即可 #include <bits/stdc++.h> using namespace std; int o ...

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

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

  9. HDU 1430 魔板(康托展开+BFS+预处理)

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

随机推荐

  1. 14.2.5.4 Physical Structure of an InnoDB Index InnoDB Index 的物理结构

    14.2.5.4 Physical Structure of an InnoDB Index InnoDB Index 的物理结构 所有的InnoDB indexes 是B-trees ,index ...

  2. script:查看redo产生的历史信息

    script:查看redo产生的历史信息 SQL> alter session set nls_date_format='dd-mon-yy'; SQL>  set lines 160 p ...

  3. ubuntu12.10下arm-linux-gcc交叉编译环境的搭建

    交叉编译环境搭建的原因:通俗上讲,因为嵌入式系统可用资源比较少:几十M的ARM 二三百M的flash相对我们的pc机来说资源真的没法比.所以,为了解决这种局面就将PC机等作为主机,搭建开发环境,进行编 ...

  4. ajax+jsp实现三级联动下拉框

    js文件sjld.js  : $(document).ready( function(){ $.ajax({ url:"bindZ", type:"get", ...

  5. minidump详细介绍

    Effective minidump 简介 在过去几年里,崩溃转储(crash dump)成为了调试工作的一个重要部分.如果软件在客户现场或者测试实验室发生故障,最有价值的解决方式是能够创建一个故障瞬 ...

  6. WinDBG 技巧:如何生成Dump 文件(.dump 命令)

    程序崩溃(crash)的时候, 为了以后能够调试分析问题, 可以使用WinDBG要把当时程序内存空间数据都保存下来,生成的文件称为dump 文件. 步骤: 1) 打开WinDBG并将之Attach 到 ...

  7. [Oracle] 常用工具集之 - SQL*Loader

    SQL*Loader原理 SQL*Loader是Oracle提供的用于数据加载的一种工具,它比较适合业务分析类型数据库(数据仓库),能处理多种格式的平面文件,批量数据装载比传统的数据插入效率更高.其示 ...

  8. [Android学习笔记]Android调试

    Eclipse Debug 快捷键: [Ctrl + Shift + B]: 添加/取消断点 [F5]:进入方法中 [F6]:单步执行 [F7]:执行完毕此方法 [F8]:继续执行,直接跳到下一个断点 ...

  9. C++primer原书中的一个错误(派生类using声明对基类权限的影响)

    在C++primer 第4版的 15章 15.2.5中有以下这样一段提示: "注解:派生类能够恢复继承成员的訪问级别,但不能使訪问级别比基类中原来指定的更严格或者更宽松." 在vs ...

  10. 《Android系统开发》笔记

    <Android系统开发>笔记1:Android系统概述 Android四层架构: 1. Linux Kernel&driver层 a.依赖于Linux 2.6内核,包含安全性.内 ...