#include <iostream>
#include <sys/timeb.h>
using namespace std;
const int MAX_SIZE = 100;
enum flag {blank ='X',queen = 1};
char Chess[MAX_SIZE][MAX_SIZE];//棋盘图
int n;//解决n皇后问题
int total;//用于计摆放方式
//对棋牌进行初始化
void Init()
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
Chess[i][j] = blank;
total = 0;//初始时有零中摆放方式
}
//判断(r,c)位置是否可放置,可以放置返回ture,不可放返回false
bool Judge(int r,int c)
{
int i,j;
for(i = r + 1; i < n; i++)
if(Chess[i][c] == queen)
return false;//说明c列上已有一皇后
for(i = c + 1; i < n; i++)
if(Chess[r][i] == queen)
return false;//说明r行上已有一皇后
for(i = r + 1, j = c + 1; (i < n) && (j < n); i++, j++)
if(Chess[i][j] == queen)
return false;//45度斜线上已有一皇后
for(i = r + 1, j = c - 1; (i <n) && (j >= 0); i++, j--)
if(Chess[i][j] == queen)
return false;//135度斜线上已有一皇后
return true;//排除四种情况后,说明(r,c)点可放置皇后
}
//回溯算法主程序,其中k为棋盘剩余可摆的个数,cnt为已摆放的皇后个数
//先判断棋盘是否摆放完毕,若摆完且n个皇后已经摆完,则打印摆放的图形
//未摆放完毕,则在棋盘的第k个可摆的位置进行摆放,k/n为该位置的行数,k%c为该位置的列数
//判断该位置是否可以摆放,若可以,则摆放;否则,判断k-1个位置是否可以摆放,其中第k个位置摆放第cnt个皇后时
//注意堆栈的变化:摆放第cnt个皇后时进入堆栈,该位置变为queen,之后进入下一个位置摆放第cnt+1个皇后
//摆完n个皇后后,退出堆栈,对应位置为blank
void Backtrack(int k,int cnt)
{
if((k < 0)||(cnt == n))//棋牌摆放完毕 or 以摆满n后
{
if(cnt == n)
{
printf("No.%d:\n",++total);
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf(" %c ",Chess[i][j]);
putchar('\n');
}
putchar('\n');
}
}
else
{
int r = k / n, c = k % n;
if(Judge(r,c))//可放置一皇后
{
Chess[r][c] = queen;
Backtrack(k-1,cnt+1);
Chess[r][c] = blank;
}
Backtrack(k-1,cnt);
}
}
int main(void)
{
timeb t1,t2;
long kk;
cout<<"输入皇后个数:";
while(cin>>n)
{
Init();
ftime(&t1); //初试时间
Backtrack(n*n-1,0);
ftime(&t2); //结束时间
cout<<"计算"<<n<<"皇后问题总共可有"<<total<<"种摆法!"<<endl;
kk = (t2.time-t1.time)*1000 + t2.millitm-t1.millitm;
cout<<"本次回溯耗时:"<<kk<<"毫秒"<<endl;
system("PAUSE");
cout<<"输入皇后个数:";
}
return 0;
}