点击打开链接
N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 30795 Accepted Submission(s): 13372
Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
Author
cgf
Source
Recommend
lcy | We have carefully selected several similar problems for you: 1016 1312 1181 1010 2614
回溯法:
当把问题分成若干步骤并递归求解时,如果当前步骤没有合法选择,则函数将返回上一级递归调用,这种现象称为回溯。
递归枚举算法的过程中,把生成和检查有机的结合起来,从而减少不必要的枚举,通常称为回溯算法
思路:
恰好每一行放置一个皇后,用c[x]表示第x行皇后的列编号,
则问题变为全排列生成问题,0-7的全排列为8!=40320,枚举量不会超过它
既然是逐行放置的,则皇后肯定不会横向攻击,只需要检查纵向和斜向攻击即可。
条件“ cur-C[cur] == j-C[j] || cur+C[cur] == j+C[j] ” 用来判断皇后 (cur,C[cur]) 和 (j,C[j]) 是否在同一条对角线上。
求解答案的代码:
#include<bits/stdc++.h>
using namespace std;
//n皇后
int tot;//解的个数
int c[12];//c[x]表示第x行皇后的列编号
void search(int n,int cur)
{
if(cur==n)//递归边界
tot++;//只要走到这里,所有皇后必然不冲突
else
for(int i=0;i<n;i++){//恰好每行每列各放置一个皇后
int ok=1;
c[cur]=i;//尝试把第cur行的皇后放在第i列
for(int j=0;j<cur;j++)//检查是否与前面的皇后冲突
if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])
{
ok=0;break;
}
if(ok) search(n,cur+1);//如果合法,则继续递归
}
}
int main()
{
/*
while(cin>>n&&n){
tot=0;
search(0);
cout<<tot<<endl;
}
*/
for(int n=0;n<12;n++)
{
tot=0;
search(n,0);
cout<<tot<<",";
}
return 0;
}
AC代码
#include<iostream>
using namespace std;
int main()
{
int a[]={1,1,0,0,2,10,4,40,92,352,724,2680};
int n;
while(cin>>n&&n){
cout<<a[n]<<endl;
}
return 0;
}