八皇后问题

八皇后问题:

        在国际象棋中,皇后可以在没有限定一步走几格的前提下,对棋盘中的其他棋子进行直向吃、横向吃以及对角线方向吃,皇后在放入之前必须考虑所放位置的直线方向、横向方向以及对角线方向是否已经放置了皇后

         在8*8棋盘上称其为八皇后问题,在N*N棋盘上就称其为N皇后问题

算法分析:

        八皇后问题就是利用堆栈结构以及回溯算法的策略

        在每一次放入皇后之前,都要判断所放位置的直线方向、横向方向以及对角线方向是否已经放置了皇后,如果没有放置,放皇后,然后将此皇后放入栈中(Q[++top]);反之,走下一列(二维数组存储

        如果到棋盘的 i 行放皇后,直到 j (代表列)等于7时,还没有找到合适的位置放皇后,则返回到上一行,i--,将 j 置零,重新找位置放皇后 (此乃回溯算法

       如果top(栈的大小为8)等于7,说明最后一行皇后放置完毕,完成了一组解,然后输出此组解    

代码实现:

非递归:一组解

#include<stdio.h>
#include<stdlib.h>

 //输出 
void pint(int a[8][8]){
     for(int i=0;i<8;i++) { 
       for(int j=0;j<8;j++)
        printf("%d",a[i][j]);
        printf("\n"); 
    } 
}
  void pint1(int Q[8]){
  	printf("行号:     ");
  	for(int i=0;i<8;i++){
  		printf("%d ",i);
  	}
  		printf("\n");
  		printf("皇后的列号 ");
  	for(int i=0;i<8;i++){
  		printf("%d ",Q[i]);
	  }
  	
  }

 void sortKing(int a[8][8]){
  	  int i,j,top;
       //存放皇后
        int left[15]={},right[15]={},cal[8]={};//左斜线,右斜线,放有皇后的列号
        int Q[8];//存放每一行皇后的列号
        top=-1;
        i=0,j=0;
        while(i<8){
         while(top!=7){
           for( ;j<8;j++){
             if(!cal[j]&&!left[i+j]&&!right[7+i-j]){//判断对角线和列放皇后
                   a[i][j]=1; 
                   Q[++top]=j;
                   left[i+j]=1;
                   right[7+i-j]=1;
				    cal[j]=1; 
                    i++;   
                    j=0;
            break;
           } 
        }
        //i行不能放,回溯
            if(j==8){
              i--;
              j=Q[top--];//出栈
              a[i][j]=0;
              cal[j]=0;  //列 
              left[i+j]=0;
              right[7+i-j]=0;
              j++;
          }
	} 
}
  pint1(Q);
  printf("\n输出8*8数组\n");
  pint(a);
}



int main(void){
    int a[8][8];
    for(int i=0;i<8;i++)
       for(int j=0;j<8;j++)
         a[i][j]=0;
      sortKing(a);
}

 

递归:多组解

#include<stdio.h>
#define N 8
int cnt=0;
int col[N]={0},left[2*N-1]={0},right[2*N-1]={0};
int Q[N]={0};
/*
函数作用:打印出当前的皇后的所在的位置 
函数参数:皇后数组的首地址Q,当前是第几组解cnt 
无返回值 
*/
void PrintQueen(){
	int i,k;	
	printf("第%d组解\n",++cnt);
	for(i=0;i<N;++i){
		for(k=0;k<N;++k){
			if(Q[i]==k)
				printf("Q  ");
			else
				printf("*  ");
		}
	printf("\n\n");
	}

}
/*函数作用:找出所有的皇后位置并输出打印 
函数参数:第i行数 
无返回值 
*/
void Queen(int i){
	int j;
	for(j=0;j<N;++j){
		if((!col[j])&&(!left[i+j])&&(!right[i+N-1-j])){
			Q[i]=j;
			right[i+N-1-j]=1;
			left[i+j]=1;
			col[j]=1; 
			if(i<N-1){
				Queen(i+1);  //下一行找皇后
			}
			else{
				PrintQueen(); //格满,输出
			}
			//返回抹掉皇后,继续放
			right[i+N-1-j]=0;
			left[i+j]=0;
			col[j]=0;
		}
	}
} 
int main(void){
	//找出所有的皇后位置并输出打印
	Queen(0);
	return 0;
} 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值