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*都不过, ...
随机推荐
- HDU 4704 Sum (高精度+快速幂+费马小定理+二项式定理)
Sum Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I64u Submit Status ...
- MFC中挂起线程和恢复线程
DWORD SuspendThread ( HANDLE hThread ); //挂起线程DWORD ResumeThread ( HANDLE hThread ); //恢复线程 比如说我 ...
- ubuntu修改文件访问权限
遇到“bash .....权限不够”的问题时, 从控制台进入到那个文件夹 chmod 777 * -R 全部子目录及文件权限改为 777
- [MAC] Mac OS X下快速复制文件路径的方法
在windows上复制当前目录的路径有一个特别方便的方式,只需要用鼠标点击路径栏,它就会自动变成像”D:\Downloads\tmp”这样的路径,如果要复制文件路径,只需要将目录路径和文件名拼接起来即 ...
- angularjs教程
http://www.runoob.com/angularjs/angularjs-routing.htmlA
- 微信api退款操作
状况:证书加载进去,本地调试退款成功,然而发不到iis上却是不成功. 分析:定然是iis配置问题. 问题一:证书加载不进去,出现“内部错误” 解决:在iis中找到对应的应用连接池,右键高级设置,找到“ ...
- hdu 1728 bfs **
简单bfs,记录好状态即可 #include<cstdio> #include<iostream> #include<algorithm> #include< ...
- Struts2拦截器原理以及实例
一.Struts2拦截器定义 1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2. ...
- Fragments碎片
A Fragment represents a behavior or a portion of user interface in an Activity. 在一个Activity活动中,一个Fra ...
- HUE的时区问题
转自 http://molisa.iteye.com/blog/1953390 我主要是根据这个说明调整的HUE的时区问题 在使用Cloudera Hue时遇到一问题: 1. 使用Sqoop导入功 ...