C++程序算法题--N皇后
题目
N 皇后演示程序
在N×N格的棋盘上放置彼此不受攻击的N 个皇后,按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子,求解可以放置的布局方式。
设计要求:
(1) 要求实现图形化棋盘显示;
(2) 要求实现N 皇后布局演示,可以使用方向键进行布局切换。
思路
就是暴力搜索,一个位置一个位置的试。所以缺点显而易见,只能算<=10的情况,超过10就无法计算了。
首先先简化问题,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子,设两个棋子的坐标分别为x1,y1,x2,y2.所以当|x1-x2|=|y1-y2|就冲突了。因为是一行一行的放,所以行冲突不用考虑,只需要考虑列冲突即y1!=y2。具体看代码和注释
代码:
#include<iostream>
#include<conio.h>
#include<stdlib.h>
#include<cmath>
using namespace std;
int n,tol=0; // N皇后个数和成功个数
int queen[100] = {0}; //[]里的值代表行数,value值代表列数
int col[1000][100] = {0}; //用来存放成功的数据
bool check(int r,int c){ // (r,c)代表新皇后的坐标
for(int i=0;i<r;i++){
if(queen[i]==c||(abs(queen[i]-c) == abs(r-i))){ // 判断是否冲突
return false;
}
}
return true;
}
void DFS(int r){
if(r==n){ //判断最后一个是否已经放到棋盘
for(int i=0;i<n;i++){
col[tol][i] = queen[i]; //讲棋盘存到总的期盼里
}
tol++; //成功次数++
queen[100] = {}; //初始临时棋盘
return;
}
for(int c=0;c<n;c++){
if(check(r,c)){ //判断该位置是否与前n-1个位置冲突
queen[r] = c; //不冲突赋值
DFS(r+1); //进行一下行操作
}
}
}
void show(int r){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(col[r][i]==j){
cout<<"Q ";
}else{
cout<<"X ";
}
}
cout<<endl<<endl;
}
cout<<"************当前页数"<<r+1<<"************"<<endl<<endl;
cout<<"*********->查看下一个,<-查看上一个*********"<<endl;
}
int main(){
cout<<"请输入皇后的数量:";
cin>>n;
if(n<3){
cout<<"无解!"<<endl;
return 0;
}
DFS(0);
cout<<"一共有"<<tol<<"种布局"<<endl<<endl;
int ch1=0;
int ch2=0;
int current = 0;
show(current);
while (1){
if (ch1=getch()){
ch2=getch();//第一次调用getch(),返回值224
switch (ch2){//第二次调用getch()
case 75: {
if(current-1>=0){
current--;
}else{
current = tol-1;
}
system("cls\n");
cout<<"请输入皇后的数量:"<<n<<endl;
cout<<"一共有"<<tol<<"种布局"<<endl<<endl;
show(current);
break;
}
case 77: {
if(current+1<=tol-1){
current++;
}else{
current = 0;
}
system("cls\n");
cout<<"请输入皇后的数量:"<<n<<endl;
cout<<"一共有"<<tol<<"种布局"<<endl<<endl;
show(current);
break;
}
default:cout<<"输入错误!"<<endl;break;
}
}
}
return 0;
}
运行结果:可以通过键盘方向键来进行布局的转换