记录编号 82230 评测结果 AAAAAA
题目名称 拉丁正方形 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.214 s
提交时间 2013-11-22 17:59:13 内存使用 6.62 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
const ll SIZEN=8;
vector<pair<ll,ll> > scanlis;//按照何种顺序搜索
bool line[SIZEN][SIZEN]={0};//行信息,[i][j]=1表示第i行有j
bool row[SIZEN][SIZEN]={0};//列信息,意义类似
ll board[SIZEN][SIZEN]={0};
ll fact[]={1,1,2,6,24,120,720,5040,40320,362880,3628800};
ll n;
ll sum;
ll cnt[1000000]={0};
void print(ll s[SIZEN][SIZEN]){//调试接口
	ll i,j;
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++) cout<<s[i][j]<<" ";
		cout<<endl;
	}
}
bool flag[SIZEN]={0};
ll getring(ll x){
	ll tot=0;
	ll now=x;
	do{
		tot++;
		flag[now]=true;
		now=board[2][now];
	}while(now!=x);
	return tot;
}
ll id=0;
bool legal(void){
	memset(flag,0,sizeof(flag));
	ll i;
	ll temp;
	id=0;
	for(i=1;i<=n;i++){
		if(!flag[i]){
			temp=getring(i);
			id=max(id,temp);
		}
	}
	if(cnt[id]){
		return false;
	}
	return true;
}
void fillblock(ll x,ll y,ll i){
	line[x][i]=true;
	row[y][i]=true;
	board[x][y]=i;
}
void eraseblock(ll x,ll y,ll i){
	board[x][y]=0;
	line[x][i]=false;
	row[y][i]=false;
}
void DFS(ll k){//现在需要确定scanlis中的第k个位置
	if(k==scanlis.size()){
		sum++;
		cnt[id]++;
		return;
	}
	ll i;
	ll x,y;//x行y列
	x=scanlis[k].first,y=scanlis[k].second;
	for(i=1;i<=n;i++){
		if(line[x][i]||row[y][i]) continue;
		if(x==2&&y==n){
			fillblock(x,y,i);
			if(legal()){
				DFS(k+1);
			}
			else sum+=cnt[id];
			eraseblock(x,y,i);
			return;
		}
		fillblock(x,y,i);
		DFS(k+1);
		eraseblock(x,y,i);
	}
}
void init(void){
	scanf("%lld",&n);
	ll i,j;
	for(i=2;i<n;i++){
		for(j=2;j<=n;j++) scanlis.push_back(make_pair(i,j));
	}
	for(i=1;i<=n;i++) fillblock(1,i,i);
	for(i=2;i<=n;i++) fillblock(i,1,i);
}
int main(){
	freopen("latinus.in","r",stdin);
	freopen("latinus.out","w",stdout);
	init();
	DFS(0);
	sum*=fact[n-1];
	cout<<sum<<endl;
	return 0;
}