洛谷 P1219 [USACO1.5]八皇后 Checker Challenge题解--zhengjun

一看题目,搜索题啊。

首先,枚举排列,然后验证是否在同一条斜线上

设有两个点是 \(i,j\)

那么如果他们在从左上到右下↘的斜线上,那么一定满足\(X_i-Y_i=X_j-Y_j\)

如果他们在从左下到右上↗的斜线上,那么一定满足\(X_i+Y_i=X_j+Y_j\)

所以打出代码:

#include<cstdio>
#include<cstring>
using namespace std;
int n;
int a[14],vis[14],cnt;
int f[30];
void dfs(int i){
	if(i==n+1){
		memset(f,0,sizeof(f));
		for(int j=1;j<=n;j++){
			if(f[j+a[j]])return;
			f[j+a[j]]=1;
		}
		memset(f,0,sizeof(f));
		for(int j=1;j<=n;j++){
			if(f[j-a[j]+n])return;
			f[j-a[j]+n]=1;
		}
		cnt++;
		if(cnt<=3){
			for(int j=1;j<=n;j++)printf("%d ",a[j]);
			printf("\n");
		}
		return;
	}
	for(int j=1;j<=n;j++){
		if(!vis[j])vis[j]=1,a[i]=j,dfs(i+1),vis[j]=a[i]=0;
	}
}
int main(){
	scanf("%d",&n);
	dfs(1);
	printf("%d",cnt);
	return 0;
}

然后你会发现 \(TLE\)

考虑优化,我们可以在放棋子的时候就把在同一斜线的给排除掉

#include<cstdio>
#include<cstring>
using namespace std;
int n;
int a[14],vis[14],cnt;
int f[30],g[30];
void dfs(int i){
	if(i==n+1){
		cnt++;
		if(cnt<=3){
			for(int j=1;j<=n;j++)printf("%d ",a[j]);
			printf("\n");
		}
		return;
	}
	for(int j=1;j<=n;j++){
		if(!vis[j]){
			if(f[i+j])continue;
			if(g[i-j+n])continue;
			f[i+j]=g[i-j+n]=1;
			vis[j]=1,a[i]=j,dfs(i+1),vis[j]=a[i]=0;
			f[i+j]=g[i-j+n]=0;
		}
	}
}
int main(){
	scanf("%d",&n);
	dfs(1);
	printf("%d",cnt);
	return 0;
}
posted @ 2022-06-11 15:02  A_zjzj  阅读(15)  评论(0编辑  收藏  举报