八皇后问题之解决方案
---------July
------
经典问题n皇后问题,之解决方案(解决4~15皇后)。
已测试运行通过。接近完美。
恐怕网上再也找不到有关此类n皇后问题,如此完善实用的设计了。
July。。2010/06月。
----------------------------------------------------------
// QueensSolutionWithVS05-OOP.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include "time.h"
#include "iostream"
#include "fstream"
#include "limits"
using namespace std;
class QueensSolution
{
private:
int* queen; //用于缓存每一种解
int flag; //回溯标志,0表示回溯,1表示不回溯
int column; //用于记录当前所在列
int row; //用于记录当前所在行
int value; //用于记录皇后可在位置
int queensnum; //皇后的数量
public:
int count; //用于统计满足条件的皇后组合方式数
QueensSolution(int size); //构造函数
void calResult(); //主要函数用于计算
void show(); //显示结果用函数
void outToFile(); //将结果保存到文件
int getNextQueensPosition(int row); //获得下一个皇后位置
};
QueensSolution::QueensSolution(int inputsize)
{
queen = new int[inputsize+1];
flag=1;
count=0;
queensnum=inputsize;
}
void QueensSolution::calResult()
{
for(column=1;column<queensnum+1;column++)//列循环
{
queen[1]=column; //首个皇后所在列,每次列循环向后移动一位
for(row=1;row<queensnum;row++) //行循环
{
if(row==0) //如果回退到row=0,则说明首个皇后在column列时的所有解已列出
{
flag=1; //flag置为初值1
break; //跳出行循环
}
value=getNextQueensPosition(row+1); //获得下一行皇后所在的位置
if(value!=0)
{
queen[row+1]=value; //存储下一行皇后所在位置
flag=1;
}
else //没找到合适的值,说明此种组合结果无解,回溯到上一行,并将该皇后后移后继续计算
{
flag=0; //0表示需要回溯
row=row-2; //回到上一行
}
if(row==queensnum-1)//到达最后一行,算出一个结果并且开始输出
{
count++;
show(); //命令行输出
outToFile(); //输出到文件
flag=0;
row=row-2;
}
}
}
return;
}
int QueensSolution::getNextQueensPosition(int row)
{
int position=0; //用于存储皇后位置
int init=1; //起始位置
if(!flag) //如果flag=0,则需要回溯
{
init=queen[row]+1;//当前列的下一列为起始列
if(init>queensnum) //列越界的情况,返回值0,代表已无解,需回溯到上一行
{
return 0;
}
}
for(int j=init;j<queensnum+1;j++) //j为列
{
for(int i=1;i<row;i++) //i为行
{
if( queen[i]==j || queen[i]==(j-row+i) || queen[i]==(j+row-i) )
//判断列是否安全,正对角线是否安全,反对角线是否安全。
//不明白的话,用笔在纸上画下,计算下就ok了/July。
{
break; //在横竖斜方向存在皇后,不满足条件,跳出行循环
}
if( i==row-1 ) //i循环到了row-1仍满足条件,证明此列为正解
{
position=j;
return position;
}
}
}
return position;
}
void QueensSolution::show()
{
cout << "=====================" << endl;
cout <<"第"<<count<<"种结果组合:\n";
cout << "=====================" << endl;
cout << " ";
for(int l1=0;l1<queensnum;l1++)
{
cout << l1+1 << " ";
}
cout << endl;
cout << " ┌";
for(int l2=0;l2<queensnum;l2++)
{
cout << "─";
}
cout << "┐";
cout << endl;
for(int i=1;i<queensnum+1;i++)
{
if(i<10)
{
cout << " ";
}
cout << i << "│";
for(int k1=0;k1<queen[i];k1++)
{
if(k1!=0)
{
cout << "□";
}
}
cout<<"●";
for(int k2=0;k2<queensnum-queen[i];k2++)
{
cout << "□";
}
cout<<"│"<< endl;
}
cout << " └";
for(int l3=0;l3<queensnum;l3++)
{
cout << "─";
}
cout << "┘";
cout << endl;
}
void QueensSolution::outToFile()
{
ofstream outf;
outf.open("out.txt",ios::app);
outf << "=====================" << endl;
outf <<"第"<<count<<"种结果组合:\n";
outf << "=====================" << endl;
outf << " ";
for(int l1=0;l1<queensnum;l1++)
{
outf << l1+1 << " ";
}
outf << endl;
outf << " ┌";
for(int l2=0;l2<queensnum;l2++)
{
outf << "─";
}
outf << "┐";
outf << endl;
for(int i=1;i<queensnum+1;i++)
{
if(i<10)
{
outf << " ";
}
outf << i << "│";
for(int k1=0;k1<queen[i];k1++)
{
if(k1!=0)
{
outf << "□";
}
}
outf<<"●";
for(int k2=0;k2<queensnum-queen[i];k2++)
{
outf << "□";
}
outf<<"│"<< endl;
}
outf << " └";
for(int l3=0;l3<queensnum;l3++)
{
outf << "─";
}
outf << "┘";
outf << endl;
outf.close();
}
//#include "QueensSolution.h"
void clearStreamBuffer()
{
//读到非法字符后,输入流将处于出错状态,
//为了继续获取输入,首先要调用 clear 函数
//来清除输入流的错误标记,然后才能调用
//ignore 函数来清除输入流中的数据。*/
cin.clear();
//ignore 函数在此将把输入流中的数据清空。 */
cin.ignore( numeric_limits<streamsize>::max(),'\n');
return;
}
int main()
{
double starttime=0,endtime=0,wholetime=0;
cout<<"┌──────────────────────────────┐\n";
cout<<"│ n皇后问题之解决方案 │\n";
cout<<"│ 东华理工大学 软件学院 曹硕 July 2010/6月 │\n";
cout<<"└──────────────────────────────┘\n";
START:
int Queens;
cout << "请输入皇后的数量:";
cin >> Queens;
if(Queens>15||Queens<4)
{
cout << "输入有误,请您重新输入4~15之间的数!\n" << endl;
clearStreamBuffer();
goto START;
return 0;
}
starttime=(double)clock();
QueensSolution qs(Queens);
qs.calResult();
endtime=(double)clock();
wholetime = endtime - starttime;
cout << "=====================" << endl;
cout << "总共耗时:" << wholetime << "ms" << endl;
cout << "=====================" << endl;
cout << "共有" << qs.count << "种解决方案。"<< endl;
cout << "=====================\n" << endl;
cout << "继续运算请按Y,按任意键退出退出!";
char ch;
clearStreamBuffer();
ch=getchar();
if(ch!='Y' && ch!='y')
{
cout << "感谢您使用本软件,再见!" << endl;
}
else
{
goto START;
}
system("pause");
return 0;
}
--------------
以下的东西均为网上搜集。
-------------- ----------------------------------------------------------
#include<stdio.h>
#define N 8
int layout[N];//布局
int key=0;
int judge(int row, int col)//判断能否在(row,col)放下
{
int i;
for(i=0;i<row;i++)
{
if(layout[i]==col)
return 0; //同一列
if(i-layout[i]==row-col) //layout[i]==col+i-row; 若为4皇后问题,则row为5
return 0; //同一条主对角线
if(i+layout[i]==row+col) //layout[i]==col-i+row; row同上
return 0; //同一条副对角线
}
return 1;
}
void lay(int row) //在row行上放Queen
{
int i;
if (row==N) //放完N个Queen输出布局
{
printf("\n%02d ", ++key);
for(i=0;i<N;i++)
printf("%c%d ",layout[i]+'a',i+1);
}
else
{
for(i=0;i<N;i++)//在i列上放Queen
{
layout[row]=i;
if(judge(row,i))
lay(row+1);
}
}
}
void main()
{
lay(0);
printf("\n");
}
-------------- ------------------------------------------------------------------------
#include "stdio.h"
#define MAX_X 8
#define MAX_Y 8
#define OBS
(MAX_X-1)
int P[MAX_X][MAX_Y];//Queen's point,true == has Queen,false == not has
int L[MAX_X*2-1];//MAX_X*2-1 is the number of Diagonal-L; L is the states of left Diagonal,
//true == this left Diagonal not locked, false == this left Diagonal is locked
int R[MAX_Y*2-1];//MAX_Y*2-1 is the number of Diagonal-R; R is the states of right Diagonal,
//true == this right Diagonal not locked, false == this right Diagonal is locked
int C[MAX_Y];//states of colums
//false == this colum is locked; true == this colum is not locked
int nNumberOfFunctions = 0;
void PutNextOne(int nLine);
void PrintPoint()
{
int i = 0;
int j = 0;
printf("Function %d is:\r\n",nNumberOfFunctions);
for(i = 0; i < MAX_X; i++)
{
for(j = 0; j < MAX_Y; j++)
{
if(P[i][j] == 1)
{
printf("x = %d, y = %d\r\n",i,j);
}
}
}
printf("\r\n");
}
void PutNextOne(int nLine)
{
int i = 0;
if(nLine >= MAX_X)
{
nNumberOfFunctions++;
PrintPoint();
return ;
}
for(i = 0; i < MAX_Y; i++)
{
if((C[i] == 1) && (L[nLine+i] == 1) && (R[nLine-i+OBS] == 1))
{
C[i] = 0;
L[nLine+i] = 0;
R[nLine-i+OBS] = 0;
P[nLine][i] = 1;
PutNextOne(nLine+1);
C[i]= 1;
L[nLine+i] = 1;
R[nLine-i+OBS] = 1;
P[nLine][i] = 0;
}
}
return;
}
void main()
{
int i = 0;
int j = 0;
for(i = 0; i < MAX_Y; i++)
{
C[i] = 1;
}
for(i = 0; i < MAX_X*2-1; i++)
{
L[i] = 1;
}
for(i = 0; i < MAX_Y*2-1; i++)
{
R[i] = 1;
}
for(i = 0; i < MAX_X; i++)
{
for(j = 0; j < MAX_Y; j++)
{
P[i][j] = 0;
}
}
PutNextOne(0);
}
//待续。。还有很多的问题有待解决。。
//第一个程序。本人只负责调试,修正,测试。July\0614。