n后问题
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
•解向量:(x1,x2,… , xn)
•显约束:xi=1,2,… ,n
•隐约束:
1)不同列:xi¹xj
2)不处于同一正、反对角线:|i-j|¹|xi-xj|
//n后问题2.0
#include <iostream>
#include <cstdlib>
using namespace std;
class Queen{
friend int nQueen(int);
private:
bool Place(int k);
void Backtrack(void);
int n, //皇后个数
*x; //当前解
long sum; //当前已找到的可行方案数
};
bool Queen::Place(int k)
{
for(int j = 1; j < k; j++)
{
if((abs(k-j) == abs(x[j] - x[k])) || (x[j] == x[k]))
return false;
}
return true;
}
void Output(int n, int x[]) //输出棋盘
{
cout<<"[";
for(int i = 1; i < n; i++)
{
cout<<x[i]<<",";
}
cout<<x[n]<<"]"<<endl;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(j == x[i])
{
cout<<"Q ";
} else {
cout<<"# ";
}
}
cout<<endl;
}
}
void Queen::Backtrack(void)
{
x[1] = 0;
int k = 1;
while(k > 0){
x[k] += 1;
while((x[k] <= n) && !(Place(k)))
{
x[k] += 1;
}
if(x[k] <= n)
{
if(k == n){
Output(n,x);
cout<<endl;
sum++;
} else {
k++;
x[k] = 0;
}
} else {
k--;
}
}
}
int nQueen(int n)
{
Queen X;
//初始化X
X.n = n;
X.sum = 0;
int *p = new int[n+1];
for(int i = 0; i <= n; i++)
{
p[i] = 0;
}
X.x = p;
X.Backtrack();
delete[] p;
return X.sum;
}
int main()
{
int n; //皇后个数
int s; //问题解个数
cout<<"请输入皇后个数:"<<endl;
cin>>n;
cout<<n<<"皇后问题解有:"<<endl;
s = nQueen(n);
cout<<n<<"皇后问题共有"<<s<<"种解法!"<<endl;
return 0;
}