码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-08-30 13:32:25      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

魔板

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+预处理)

标签:

原文地址:http://www.cnblogs.com/Blackops/p/5821551.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!