问题描述以及样例输入输出
Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1 8 5 0
Sample Output
1 92 10
思路(回溯+递归):
从棋盘第一行往下逐层判断,用一维数组就够了,不用二维数组。
用一维数组Board[]存第i行第j列是否有皇后,初始一维数组的值都为-1,Board[3][4]就表示第3行第4列有象棋。
首先有一个判断函数Feasible(x,y)判断x,y处能否放置棋子,函数内容是判断x,y与前x-1行有没有存在同对角线,同列就ok,肯定不在同一行,所以不用判断行。
再就是递归函数,参数为deep,代表当前深度,当到第N+1行时递归结束,否则就判断deep行所有列中有没有满足条件的,有就再往下一层,直到递归结束。
AC代码:
/*
* @Author: robot-cmy
* @Date: 2021-11-27 10:08:20
* @Last Modified by: robot-cmy
* @Last Modified time: 2021-11-27 10:52:22
*/
#include <iostream>
#include <memory.h>
#include <stdio.h>
using namespace std;
int Board[10]; //一维数组从上往下存第几行第几列有棋子
int N; //棋盘深度
int answerCount; //解的个数
bool Feasible( int x, int y ) {
//判断x,y与前x-1行
for( int i = 0; i < x ; i++ ) {
//判断对角线与列,不用判断行
if( ( i + Board[i] == x + y ) || ( i - Board[i] == x - y ) ||
Board[i] == y ) {
return false;
}
}
return true;
}
void nQueen( int deep ) {
if( deep >= N ) { //到第N+1层,递归结束
answerCount++;
} else {
// deep行所有列中中有没有满足条件的
for( int i = 0; i < N; i++ ) {
if( Feasible( deep, i ) ) {
Board[deep] = i; //记录列
nQueen( deep + 1 ); //往下一层
}
}
}
}
int main() {
while( scanf( "%d", &N ), N ) {
answerCount = 0; //初始化=0
memset( Board, -1, sizeof( Board ) );//初始化为-1
nQueen( 0 );
cout << answerCount << endl;
}
return 0;
}