效果:
代码:
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
using namespace std;
class Queen{
private:
int n=4; //棋盘大小
vector<int> x; //解空间
int sum=0; //解个数
vector<vector<int> > result;
public:
Queen(){};
Queen(int k);
~Queen(){};
bool Place(int k); //判断第k行的放置方法是否合法
void Back_track(int t); //寻找解
void print_result(); //输出解的个数
void print(vector<int> x,int t);
};
void Queen::print(vector<int> x,int t)
{
int row;
int col;
for(row=0; row<n; row++)
{
for(col=0; col<n; col++)
cout<<"+---";
cout<<"+"<<endl;
for(col=0; col<n; col++)
{
if(col == x[row] && row <= t)
cout<<"| * ";
else
cout<<"| ";
}
cout<<"|"<<endl;
}
cout<<"+";
for(col=0; col<n;col++)
cout<<"---+";
cout<<" ";
}
void Queen::print_result()
{
cout<<endl<<"结果个数为:"<<sum<<endl;
if(sum > 0)
{
cout<<"结果分别为:"<<endl;
for(int k=0;k<result.size();k++)
{
cout<<"结果"<<k+1<<':'<<endl;
print(result[k],n);
cout<<endl<<endl;
}
}
}
Queen::Queen(int k)
{
n=k;
x.resize(k);
}
bool Queen::Place(int k) //判断第k行的放置是否符合规则
{
for(int i=0;i<k;i++)
{
if((abs(k-i)==abs(x[k]-x[i])) ||x[k]==x[i]) //如果第k行和前面的任一行的位置在同一条对角线上或者是在同一列上,就返回false
return false;
}
return true;
}
void Queen::Back_track(int t)
{
if(t >= n) //当要判断的行数超过棋盘大小时,证明前面n行的棋盘是合法的
{
sum++;
result.push_back(x);
cout<<endl<<"回溯中"<<endl;
print(x,n);
cout<<"成功!";
if(x[t] != n-1)
cout<<"继续回溯同一行下一个位置"<<endl;
else
cout<<"继续回溯上一行的下一个位置"<<endl;
}
else
{
for(int i = 0; i < n; i++)
{
cout<<endl;
x[t] = i; //每次第t行都从第1个位置开始放置,如果放置合法,就继续尝试下一行,如果放置不合法,就尝试放置下一个位置
cout<<"回溯中:"<<endl;
print(x,t);
if(Place(t))
{
cout<<"位置正确,尝试放下一行位置"<<endl;
Back_track((t+1));
}
else
{
if(i == n-1)
{
cout<<"位置错误,本行所有位置已经尝试,回溯到上一行的下一个位置";
if(t-1 >= 0 && x[t-1] == n-1)
{
cout<<",上一行的位置已经是最后一个位置,回溯到再上一行的下一个位置"<<endl;
if(t-1 == 0)
cout<<"第1行已经是最后的位置,结束回溯"<<endl;
}
else
cout<<endl;
}
else
cout<<"位置错误,尝试放同一行的下一个位置"<<endl;
}
}
}
}
int main()
{
int i;
cout<<"请输入棋盘大小:";
while(cin>>i)
{
Queen Q(i);
Q.Back_track(0);
Q.print_result();
cout<<"请输入棋盘大小:";
}
return 0;
}