Link
P2730 [USACO3.2]魔板 Magic Squares
Solve
因为只有8个数的变换,我们直接强刷BFS就可以了,关键是如何判重复的问题,我们发现8的排列数其实不多,也就(8!=40320)所以可以记录下来状态,题解中有很多康托展开的方法非常好,而且效率也很高,说实话就是一种离散的方式,这里给出康拓展开的转移
(X=a[n] imes (n-1)!+a[n-1] imes(n-2)!+...+a[i] imes(i-1)!+...+a[1] imes0!)
其中(a[i])为当前未出现的元素中是排在第几个,也就是后面有几个比我小的。这样转移的非常优秀。
但是我太懒
所以直接用一个map就给水杀过去了。
哈哈哈哈哈哈哈哈哈哈哈
Code
#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<queue>
using namespace std;
string Ans;
map<string,string> p;
queue<string> Q;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
void A_(string lst){
string now=lst;
for(int i=0;i<4;i++){
char ch=lst[i];
now[i]=lst[7-i];
now[7-i]=ch;
}
if(p.count(now)==0){
Q.push(now);
p[now]=p[lst]+'A';
}
return ;
}
void B_(string lst){
string now=lst;
now[0]=lst[3];now[1]=lst[0];now[2]=lst[1];now[3]=lst[2];now[4]=lst[5];now[5]=lst[6];now[6]=lst[7];now[7]=lst[4];
if(p.count(now)==0){
Q.push(now);
p[now]=p[lst]+'B';
}
return ;
}
void C_(string lst){
string now=lst;
now[1]=lst[6];now[2]=lst[1];now[5]=lst[2];now[6]=lst[5];
if(p.count(now)==0){
Q.push(now);
p[now]=p[lst]+'C';
}
return ;
}
void BFS(){
Q.push("12345678");
p["12345678"]="";
while(!Q.empty()){
A_(Q.front());
B_(Q.front());
C_(Q.front());
if(p.count(Ans)!=0){cout<<p[Ans].size()<<endl<<p[Ans]<<endl;return ;}
Q.pop();
}
return;
}
int main(){
freopen("P2730.in","r",stdin);
freopen("P2730.out","w",stdout);
for(int i=1;i<=8;i++){
int x=read();
Ans+=x+'0';
}
BFS();
return 0;
}