八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。
本方法采用回溯法
代码如下:
#include <stdio.h>
#include<time.h>
#include<stdlib.h>
//queen[row]=col表示第row行的第col列元素为1,该行的其他元素为0
int count=0;
int queennum;
FILE *fp;
int FindPos(int* queen,int row, int col)//返回该行可以放皇后的列号
{
int i,j;
for(j=col;j<queennum;j++)
{
for(i=0;i<row;i++)
{
if(queen[i]==j)//同一列有皇后
break;
if(j+row-i<queennum && j+row-i>=0 && queen[i]== j+row-i)//45度方向的对角线上有皇后
break;
if(j-row+i<queennum && j-row+i>=0 && queen[i]==j-row+i)//135度方向的对角线上有皇后
break;
}
if(i==row)
return j;
}
return -1;
}
void show(int* queen)
{
int i,j;
for(i=0;i<queennum;i++)
{
for(j=0;j<queennum;j++)
{
if(queen[i]==j)
{
printf(" 1");
fprintf(fp," 1");
}
else
{
printf(" 0");
fprintf(fp," 0");
}
}
printf("\n");
fprintf(fp,"\n");
}
printf("\n");
fprintf(fp,"\n");
}
void Fun(int* queen)
{
int i,j,pos;
for(i=0;i<queennum;i++)
{
pos=FindPos(queen,i,0);
label: while(pos==-1)//没有合适的位置,回溯一行
{
i--;
if(i<0) break;
pos=queen[i];
queen[i]=0;
pos=FindPos(queen,i,pos+1);//从上一位置的下一列开始查找合适的位置
}
if(pos==-1) break;
else
{
queen[i]=pos;
if(i==queennum-1)
{
show(queen);
count++;
queen[i]=0;
i--;//回溯到倒数第二行
pos=queen[i];
queen[i]=0;
pos=FindPos(queen,i,pos+1);
goto label;
}
}
}
}
int main()
{
int* queen;
int i;
double starttime=0,endtime=0,wholetime=0;
starttime=(double)clock();
printf("input the number of queen\n");
scanf("%d",&queennum);
queen=(int*)malloc(sizeof(int)*(queennum+1));
for(i=0;i<queennum;i++)
queen[i]=0;
fp=fopen("a.txt","w+");
Fun(queen);
printf("%4d\n",count);
endtime=(double)clock();
wholetime = endtime - starttime;
printf("time is %f",wholetime);
return 0;
}