P1219 [USACO1.5] 八皇后 Checker Challenge

[USACO1.5] 八皇后 Checker Challenge

题目描述

一个如下的 6 × 6 6 \times 6 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

P1219 [USACO1.5] 八皇后 Checker Challenge_第1张图片

上面的布局可以用序列 2   4   6   1   3   5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5 来描述,第 i i i 个数字表示在第 i i i 行的相应位置有一个棋子,如下:

行号 1   2   3   4   5   6 1\ 2\ 3\ 4\ 5\ 6 1 2 3 4 5 6

列号 2   4   6   1   3   5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 3 3 个解。最后一行是解的总个数。

输入格式

一行一个正整数 n n n,表示棋盘是 n × n n \times n n×n 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

样例 #1

样例输入 #1

6

样例输出 #1

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 6 ≤ n ≤ 13 6 \le n \le 13 6n13

题目翻译来自NOCOW。

USACO Training Section 1.5
-------------------------------------------------------------蒟蒻的分割线-------------------------------------------------------------

思路

	太累了,改天完善思路总结

难点

	太累了,改天完善思路总结

引用Linux 的创始人 Linus Torvalds 的一句话:
在这里插入图片描述

CODE

#include
using namespace std;
/*
1.同列的点j的值都是一样的
2.同逆对角线,i+j的值相同
3.同主对角线,i-j的值相同
当在某i行挑了一个点,则对应j列设为1
然后将对应的第i-j,i+j个元素设为1 
=0没有被选
因为每行填一个,所以对于行不约定限制(本来一行中其他的也不能选,但我只选一个也可以体现)
在代码中
i-j可能小于零,我们加上n(矩阵宽度)就行
*/
/*
对于题设,i+j=26,我们设矩阵宽度为30 
*/ 
int n,col[30],zdjx[30],fdjx[30],ans[15];//全局变量数组默认置0;
//int count=0; //count定义全局变量出错,我们定义在函数内部,static修饰 
int num=0;//算了,还是换个名吧,事儿太多 
void setvalue(int x,int y,int booll){
	ans[x]=y;
	col[y]=booll;		//列丨看作一,构成一个数组 
	zdjx[x+y]=booll;	//主对角线\看作一,构成一个数组 
	fdjx[x-y+n]=booll;	//主对角线/看作一,构成一个数组 
}
void dfs(int step){//step步长,代表搜索到了第几行 
	if(step>n){//搜索完第n行后,会大于n,并意味着找到了解  
		num++;
		if(num<=3){//如果解的个数小于等于3,还要输出前几个解ans 
			for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
			cout<<endl;
		} 
		return;
	}
	for(int i=1;i<=n;i++){//i为列 
		if(col[i]||zdjx[step+i]||fdjx[step-i+n])continue;//被占领,寻找该行下一个列 
		setvalue(step,i,1);//将step行,i列的标记置为1 
		dfs(step+1);
		setvalue(step,i,0);
	}
}
int main(){
	cin>>n;
	dfs(1);
	//可能性在count中,每次确定的解在ans中 
	cout<<num;
	return 0;
} 

你可能感兴趣的:(洛谷刷题,算法,c++,深度优先)