八皇后及n皇后问题

皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯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;
}
 
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值