HDU 1430 魔板(康托展开+BFS+预处理)
魔板
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2921 Accepted Submission(s): 649
1 2 3 4
8 7 6 5
对于魔板,可施加三种不同的操作,具体操作方法如下:
A: 上下两行互换,如上图可变换为状态87654321
B: 每行同时循环右移一格,如上图可变换为41236785
C: 中间4个方块顺时针旋转一格,如上图可变换为17245368
给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。
题目链接: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+预处理)的更多相关文章
- hdu 1430 魔板 康托展开 + 很好的映射
http://acm.hdu.edu.cn/showproblem.php?pid=1430 如果从start ---> end,每一次都bfs进行,那么就肯定会超时. 考虑到先把start映射 ...
- HDU - 1430 魔板 【BFS + 康托展开 + 哈希】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路 我刚开始 想到的 就是 康托展开 但是这个题目是 多组输入 即使用 康托展开 也是会T的 ...
- hdu.1430.魔板(bfs + 康托展开)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- HDU - 1430 魔板 (bfs预处理 + 康托)
对于该题可以直接预处理初始状态[0, 1, 2, 3, 4, 5, 6, 7]所有可以到达的状态,保存到达的路径,直接打印答案即可. 关于此处的状态转换:假设有初始状态为2,3,4,5,0,6,7,1 ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- [HDU 1430] 魔板
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- hdu 1430 魔板 (BFS+预处理)
Problem - 1430 跟八数码相似的一题搜索题.做法可以是双向BFS或者预处理从"12345678"开始可以到达的所有状态,然后等价转换过去直接回溯路径即可. 代码如下: ...
- hdu1430 魔板(康拓展开 bfs预处理)
魔板 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3
http://acm.hdu.edu.cn/showproblem.php?pid=3567 相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过, ...
随机推荐
- MyEclipse内存溢出问题解决方法
tomcat从1.7换到1.6,一直报这个错:java.lang.reflect.InvocationTargetException 解决方法: 加入: -server -Xms512m -Xmx20 ...
- extjs插件开发上传下载文件简单案例
前台,extjs,框架,mybatis,spring,springMVC,简单的文件上传下载案例. 必要的jar包,commons-fileupload-1.3.1.jar,commons-io-2. ...
- linux常见问题集锦-2
http://zhangge.net/1986.html 在此感谢作者分享 1.linux如何挂在windows下的共享目录 Shell 1 mount.cifs //192.168.1.3/serv ...
- Java并发编程:Synchronized及其实现原理
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- Android之Bundle类
API文档说明 1.介绍 用于不同Activity之间的数据传递 1.重要方法 clear():清除此Bundle映射中的所有保存的数据. clone():克隆当前Bundle containsKey ...
- [转]有关USES_CONVERSION
转自:http://blog.csdn.net/p40614021/article/details/6778100 ATL:转换宏是各种字符编码之间进行转换的一种很方便的方式,在函数调用时,它们显得非 ...
- 使用Antlr实现简单的DSL
为什么要使用DSL DSL是领域专用语言,常见的DSL有SQL,CSS,Shell等等,这些DSL语言有别于其他通用语言如:C++,Java,C#,DSL常在特殊的场景或领域中使用.如下图: 领域专用 ...
- SWFUpload上传大文件(暂时用用,真正用的时候还是要改的)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- J2EE面试题集锦(附答案)
转自:http://blog.sina.com.cn/s/blog_4e8be0590100fbb8.html J2EE面试题集锦(附答案)一.基础问答 1.下面哪些类可以被继承? java.lang ...
- [转]Android的Handler总结
一.Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线 ...