P1219 八皇后 题解 (dfs 深度优先搜索)

P1219 八皇后

  • 题目
  • 分析
    • 题目大意
    • 解题思路
  • 代码
  • 传送门

题目

检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
P1219 八皇后 题解 (dfs 深度优先搜索)_第1张图片
上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 6

列号 2 4 6 1 3 5

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

输入格式:
一个数字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

分析

题目大意

经典题目了,所不同的的是,本题要求依次输出前三个排法的列数,同时记录解法的个数并输出。

解题思路

这里采用的是深搜去遍历所有的可能排法。我们需要做的就是尽可能去简化在判定能否放置棋子时的步骤。

若要放置一枚棋子,需要判定该棋子同一行、同一列和左右两条对角线是否存在别的棋子,如果一个一个去遍历,不仅复杂还会花费大量的内存去存储每一个点,所以我们需要寻找方法来简化问题。
首先观察题目中所给出的图可以发现,若设棋盘的行列坐标分别为y,x,那么,与p点所在的对角线符合以下规律:

  • 对于p点从右上到左下的对角线,x+y相等;
  • 对于p点从左上到右下的对角线,x-y相等;

用一个数组去存储棋子放置后的列号,保证每行有且仅有一个棋子,再用一个二维数组chess[3][i],其中chess[0][i]=1表示第i列已被放置皇后,chess[1][i]=1表示行列和为i的对角线已存在皇后(右上到左下),chess[2] [i]=2表示行列之差加上n的值为i的对角线已存在皇后(左上到右下)。具体的解法见我代码注释,我写的很详细哦~

代码

//P1219
#include
using namespace std;

//整型全局变量默认初始化为0 
const int Max = 14; //数据范围在6到13之间 
int n;
int ans[Max]; //存放皇后所在的列数 
int sum;
//对于从右上到左下的对角线,他们的行列之和相等,同样的,对于从左上到右下的对角线,他们的行列之差相等,为避免出现负数,这里又加上了总数n 
int chess[3][Max*2]; //chess[0][i]=1表示第i列已被放置皇后,chess[1][i]=1表示行列和为i的对角线已存在皇后(右上到左下),chess[2] [i]=2表示行列之差加上n的值为i的对角线已存在皇后(左上到右下) 

void dfs(int i){
	if(i>n)
    {
        sum++;
        if(sum>3) //题目要求只输出前三个解 
			return;
        else{
            for(int i=1;i<=n;i++){
            	if(i == 1)
            		cout<<ans[i];
            	else
            		cout<<" "<<ans[i];
			} 
				
            cout<<endl;
            return;
        }
    }
    
    for(int j = 1;j <= n;j++)
    {
        if(!ans[i] && !chess[0][j] && !chess[1][i+j] && !chess[2][i-j+n]) //使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子 
        {
            ans[i]=j; //存储皇后的列 
            chess[0][j]=1; chess[1][i+j]=1; chess[2][i-j+n]=1;
            dfs(i+1);
            ans[i] = 0;  //重置,方便下次搜索
            chess[0][j]=0; chess[1][i+j]=0; chess[2][i-j+n]=0;
        }
    }
	
}


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

	return 0;
}

传送门

P1219

你可能感兴趣的:(P1219 八皇后 题解 (dfs 深度优先搜索))