问题描述
已知矩阵 A,矩阵 2 行 4 列
|1 2 3 4|
|8 7 6 5|
矩阵的状态可以用序列 12345678 来表示。即从左上角开始,按顺时针方向依次写下每个数字。对于这个矩阵,我们可以有 3 种不同的操作,具体如下:
A:互相交换上下两行,如上例可变换为状态87654321;
B:两行分别循环右移一位,如上例可变换为状态41236785;
C:中间 个元素同时顺时针旋转一位,如上例可变换为状态17245368 。
现在已知矩阵的初始状态与目标状态,现在请问聪明的你,最小需要多少步变换,如果有多种方案则输出字典序最小的方案。
输入格式
输入有两行。第一行输入一个状态,表示初始状态,第二行输入一个状态,表示目标状态。两个状态长度均为 8,均由 1到 8 这 8 个数字组成,且没有重复数字。
输出格式
输出一行,输出变换的顺序。每一步变换,输出对应的编号。
样例输入
12345678
87654321
样例输出
A
AC代码
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
bool visited[87654350];
int en;
struct zhuangtai{
int data;
string step;
};
zhuangtai st;
zhuangtai a(zhuangtai z){
int t1=z.data%10;
int t2=z.data%100/10;
int t3=z.data%1000/100;
int t4=z.data%10000/1000;
int t5=z.data%100000/10000;
int t6=z.data%1000000/100000;
int t7=z.data%10000000/1000000;
int t8=z.data%100000000/10000000;
z.data=t1*10000000+t2*1000000+t3*100000+t4*10000+t5*1000+t6*100+t7*10+t8;
z.step+='A';
return z;
}
zhuangtai b(zhuangtai z){
int t1=z.data/10000;
int t2=z.data%10000;
t1 = (t1 / 10) + (t1 % 10) * 1000;
t2 = (t2 / 1000) + (t2 % 1000) * 10;
z.data=t1*10000+t2;
z.step+='B';
return z;
}
zhuangtai c(zhuangtai z){
int a,b,c,d,t1,t2;
a=z.data%10000000/1000000;
b=z.data%1000000/100000;
c=z.data%1000/100;
d=z.data%100/10;
z.data-=a*1000000+b*100000+c*100+d*10;
t1 = b;
b = a;
t2=c;
c=t1;
t1=d;
d=t2;
a=t1;
z.data+=a*1000000+b*100000+c*100+d*10;
z.step+='C';
return z;
}
void bfs(){
queue<zhuangtai>q;
visited[st.data]=1;
q.push(st);
while(!q.empty()){
zhuangtai n=q.front();
zhuangtai tmp;
q.pop();
tmp=a(n);
if(!visited[tmp.data]){
if(tmp.data==en){
cout<<tmp.step;
return;
}
visited[tmp.data] = 1;
q.push(tmp);
}
tmp=b(n);
if(!visited[tmp.data]){
if(tmp.data==en){
cout<<tmp.step;
return;
}
visited[tmp.data] = 1;
q.push(tmp);
}
tmp=c(n);
if(!visited[tmp.data]){
if(tmp.data==en){
cout<<tmp.step;
return;
}
visited[tmp.data] = 1;
q.push(tmp);
}
}
return;
}
int main(){
memset(visited,0,sizeof(visited));
cin>>st.data;
cin>>en;
bfs();
return 0;
}