SSL_1692 魔板

题意:

    把12345678按顺时针放到一个2*4的矩阵中,我们可以进行3种操作:A:上下两行交换;B:最右边一列的插入最左边;C:把中间的四个数字顺时针旋转。现在给出最终结果,求我们从12345678到最终结果的操作次数和操作序列。

思路:

    这道题是用的BFS,在判断节点的时候用哈希表优化一下。

代码:

#include<cstdio>
#include<iostream>
#include<string>
#define maxn 70013
using namespace std;
int total,tail,head,x[10],w[maxn],father[maxn];
string ans,state[maxn],a[maxn];
short rule[5][10]={{0},{8,7,6,5,4,3,2,1},{4,1,2,3,6,7,8,5},{1,7,2,4,5,3,6,8}};//把3种操作的规则存到rule里
int hx(string s)
{
	int b=0;
	for (int i=0;i<=7;i++)
	  b=b*10+s[i]-48;
	return b%maxn;
}

bool hash(string s)
{
	int fa=hx(s),i=0;
    while (i<maxn&&a[(i+fa)%maxn]!=""&&a[(i+fa)%maxn]!=s) i++;
    if (a[(i+fa)%maxn]=="") {a[(i+fa)%maxn]=s;return false;}
    else return true;
}

void print(int x)
{
	if (x==1) return;
	total++;
	print(father[x]);
	ans+=(char)w[x]+64;//递归回去求出序列
}
void bfs()
{
	father[1]=0;w[1]=0;tail=1;head=0;state[1]="12345678";a[12345678%maxn]=state[1];
	if (state[1]==state[0]) return;
	do
	{
		head++;
		for (int i=1;i<=3;i++)//3种操作
		{
			tail++;
			w[tail]=i;
			father[tail]=head;
			state[tail]="";
			for (int j=0;j<=7;j++)
			  state[tail]+=state[head][rule[i][j]-1];//C++的字符串是0~n,所以rule要减一,我们也可以在上面定义的时候把每个数减一			
			if (hash(state[tail])) tail--;//判断节点
			if (state[tail]==state[0])
			{
				print(tail);
				tail=0;
				return;
			}
		}
	}
	while (head<tail);
}
int main()
{
	for (int i=0;i<maxn;i++)
	a[i]="";
	char x;
	for (int i=0;i<8;i++)
	{
	    cin>>x;
	    state[0]+=x;//state[0]存最终结果
	}
	bfs();
	cout<<total<<endl<<ans<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值