题目描述
在魔方风靡全球之后不久,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
题意:
给定一个序列怎么通过A,B,C操作变成目态
先bfs把初态“12345678”能通过A,B,C操作能的到的序列先存下来
相当于打表,bfs搜索时其实可以通过map去重,我是用的康托展开去重的
康托展开
最后把目标项转成12345678型的
eg:
初态
4 1 3 6 7 8 2 5
可以对应成
1 2 3 4 5 6 7 8
目态
4 6 7 2 1 3 8 5
对应
1 4 5 7 2 3 6 8
所以就是可以当成12345678---->14572368
#include <bits/stdc++.h>
using namespace std;
string start="12345678";
string end1,ans[50000];
int fac[10],pos[10],vis[50000];
struct node {
string str,step;
int can;
};
int KT(string s) {
int i,j,sum = 0;
for(i = 0; i<7; i++) {
int cnt = 0;
for(j = i+1; j<8; j++)
if(s[i]>s[j])
cnt++;
sum+=cnt*fac[7-i];
}
return sum;
}
void fun_A(string &s) {
for(int i = 0; i<4; i++)
swap(s[i],s[i+4]);
}
void fun_B(string &s) {
char t=s[3];
for(int i=2; i>=0; i--)
s[i+1]=s[i];
s[0]=t;
t=s[7];
for(int i=6; i>=4; i--)
s[i+1]=s[i];
s[4]=t;
}
void fun_C(string &s) {
char t=s[1];
s[1]=s[5];
s[5]=s[6];
s[6]=s[2];
s[2]=t;
}
void bfs() {
node now,next;
queue<node> que;
now.step = "";
now.str = start;
now.can = KT(start);
vis[now.can] = 1;
ans[now.can] = "";
que.push(now);
while(!que.empty()) {
now = que.front();
string t;
int k;
t = now.str;
fun_A(t);
k = KT(t);
if(!vis[k]) {
vis[k] = 1;
next = now;
next.step+='A';
ans[k] = next.step;
next.str = t;
next.can = k;
que.push(next);
}
t = now.str;
fun_B(t);
k = KT(t);
if(!vis[k]) {
vis[k] = 1;
next = now;
next.step+='B';
ans[k] = next.step;
next.str = t;
next.can = k;
que.push(next);
}
t = now.str;
fun_C(t);
k = KT(t);
if(!vis[k]) {
vis[k] = 1;
next = now;
next.step+='C';
ans[k] = next.step;
next.str = t;
next.can = k;
que.push(next);
}
que.pop();
}
}
int main() {
fac[0] = 1;
for(int i = 1; i<10; i++)
fac[i] = fac[i-1]*i;
memset(vis,0,sizeof(vis));
bfs();
while(cin>>start>>end1) {
swap(start[4],start[7]);
swap(start[6],start[5]);
swap(end1[4],end1[7]);
swap(end1[6],end1[5]);
for(int i=0; i<8; i++)
pos[start[i]-'0'] = i+1;
for(int i=0; i<8; i++)
end1[i] = pos[end1[i]-'0'];
int k;
// cout<<KT("12345687")<<endl;
k = KT(end1);
cout << ans[k] << endl;
}
return 0;
}