题目连接:https://www.luogu.org/problem/P1219。ios
n后问题有四个限制条件,首先是行,这一行不能再有其余皇后,因为咱们是使用行来作递归,在放置第i个皇后时,必然行的条件是知足的,那么就须要考虑列和对角线的条件,首先在递归程序里须要遍历全部的列,要在这些列里找到没有被标记过的点,若是找到,那么这个点就是当前第i个皇后所在的列,能够将其记录,以后,咱们须要对这个皇后所在的列和对角线进行标记,对列的标记很简单,使用一个数组A[i]=j,表示第i个皇后占有了在第j列。这个j就是递归函数里的遍历的条件。至于对角线的标记,假设两个皇后的位置分别是(x1,y1)(x2,y2),那么怎么证实他们在一条斜线上,其实很简单,分两种状况,从左上角到右下角,这条线上的点坐标的(x1,y1)和(x2,y2), 且 x1-y1 = x2- y2 或 x1+y1 = x2+y2,则说明这2个皇后处于同一斜线上。这里能够用i+j表示表示一个占用过的斜线,用i-j表示一个占用的斜线,i-j有可能小于0,能够为其加上N来让其不至于小于0,以下程序,输入N小于等于13,那么i+j小于等于26,因此能够用一个数组来表示。因此一共须要三个数组来表示占用过的列,和两个对角线。须要注意的是递归完了以后须要回溯。数组
#include<stdio.h> #include<iostream> using namespace std; int res[14];//存储每一行放置的位置 int check_res[3][28];//判断列和对角线 int N; int answer=0; void dfs(int step){ if (step > N){ answer++; if (answer > 3){ return; } else{ for (int i = 1; i <= N; ++i){ cout << res[i] << " "; } cout << endl; return; } } for (int j = 1; j <= N; j++){ if (!check_res[0][j] && !check_res[1][step + j] && !check_res[2][step - j + N]){ res[step] = j; check_res[0][j] = 1; check_res[1][step + j] = 1; check_res[2][step - j + N] = 1; dfs(step + 1); check_res[0][j] = 0; check_res[1][step + j] = 0; check_res[2][step - j + N] = 0; } } } int main(){ cin >> N; dfs(1); cout << answer; return 0; }
递归和回溯。函数