P1219 八皇后(搜索)

题目描述

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

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

行号 1 2 3 4 5 6

列号 2 4 6 1 3 5

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

//以下的话来自usaco官方,不代表洛谷观点

特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(或是找到一个关于它的公式),这是作弊。如果你坚持作弊,那么你登陆USACO Training的帐号删除并且不能参加USACO的任何竞赛。我警告过你了!

输入输出格式

输入格式:

 

一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 复制

6

输出样例#1: 复制

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
#include 
#include 
using namespace std;
int a[1005] ,b[1005] ,c[1005],d[1005] ;
// a表示行   b表示列   c表示从左下到右上  d表示从左上到右下
/*
    这个题目,就是用的搜素和回溯的方法 ,


*/
int n ;
int ans = 0 ; //解的个数
void dfs(int i){
	if(i>n ){
		if(ans <3 ){
			for(int j = 1 ;j <=n ; j++ ){
				printf("%d ",a[j]);
			}
			printf("\n") ;
		}
		ans++ ;
		return ;
	}
	else{
		// 对于该行 ,考察对应列
		// 其中i 表示所在行 , j 表示所在列 ;
		
		// 还有一个问题 , 怎么表示两个对角线呢 ,
		// 我们发现 从左下到右上行数和列数满足 i +j = C固定值
		//  从右上到左下 行数和列数满足 i-j  = 固定值
		//  i -j 可能为负数 ,所有我们加个 n 来调整
		for(int j = 1 ; j<=n ; j++ ){
			if( (!b[j])&& (!c[i+j]) && (!d[i-j+n])){ // 如果都没有冲突
			 // 就可以放旗子;
			  a[i] = j ; // 表示在第 i 行 第j 列放了皇后
			  b[j] = 1 ;
			  c[i+j] = 1 ;
			  d[i-j+n] = 1 ;
			  dfs(i+1) ; // 考察下一行
			  a[i] = 0 ;
			  b[j] = 0 ;
			  c[j+i ] = 0 ;
			  d[i-j+n] = 0;
			}
		}
		
	}

}
int main(){
	
	cin >> n ;
	dfs(1) ;
	cout<

 

 

你可能感兴趣的:(洛谷,#,基础算法------搜,索)