1. 程式人生 > 實用技巧 >題解P2730 [USACO3.2]魔板 Magic Squares

題解P2730 [USACO3.2]魔板 Magic Squares

Link

P2730 [USACO3.2]魔板 Magic Squares

Solve

因為只有8個數的變換,我們直接強刷BFS就可以了,關鍵是如何判重複的問題,我們發現8的排列數其實不多,也就\(8!=40320\)所以可以記錄下來狀態,題解中有很多康託展開的方法非常好,而且效率也很高,說實話就是一種離散的方式,這裡給出康拓展開的轉移

\(X=a[n] \times (n-1)!+a[n-1] \times(n-2)!+...+a[i] \times(i-1)!+...+a[1] \times0!\)

其中\(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;
}