您的位置:首页 > 其它

SSL_1692 魔板

2018-03-10 11:27 239 查看

题意:

    把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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: