N皇后问题

本文介绍了一个经典的计算机科学问题——N皇后问题,并详细解释了如何利用回溯法解决该问题。文章给出了具体的算法步骤及实现代码,帮助读者理解如何确保N个皇后在N×N的棋盘上互不攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

N皇后问题

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

基本思想

在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束

1.问题描述

n皇后问题是递归和回溯法的一个典型应用。问题描述如下:对于一个n×n的棋盘,要求在其中放入互不攻击的n个皇后。
皇后的攻击范围包括:
1) 同一行
2) 同一列
3) 同一对角线(包括两个方向)

2.算法设计

问题的解可表示为x[1:n], 表示皇后i放在棋盘的第i行的第x[i]列。
a)x[i]≠x[j] ,i≠j:不允许将任何两个皇后放在同一列上;
b)|j-i|≠|x[j]-x[i]|: 不允许两个皇后位于同一条斜线上。

3.算法步骤

取K为行的编号,数组X[K]为列的编号,先令K=1,X[K]=1,然后取K=K+1,对棋盘的下一行进行检测,找到合法的位置,依次检测,直到K=N 时,输出皇后的所在的列的位置;若过程中遇到在某一行K 无合法位置,则取K=K-1,回溯到上一行,同时令X[K]=X[K]+1,再对下一行的位置进行检测,看是否有合法皇后位置,依次得到所有的结果。

程序代码如下:

#include <stdio.h> 
#include <math.h> 
typedef int bool; 
#define true  1; 
#define false  0; 
//检测皇后是否合法
bool place(int k, int *X) 
{ 
   int i;         
i=1; 
   while(i<k){ 
     if((X[i]==X[k])||(abs(X[i]-X[k])==abs(i-k)))
       return false;                                        i++;
        } 
      return true; 
}
 void  Nqueens(int n,int *X) { 
   int k;
   X[1]=1;     
k=1;//k表示棋盘的列,用X[k]表示当前列的行的编号
while(k>0){             
int i; 
    X[k]=X[k]+1; //不断的在解空间里从小到大的试探
while((X[k]<=n)&&(!place(k, X))) 
    X[k]=X[k]+1; //不符合条件的马上再取解空间的下一个值来试探。
    if(X[k]<=n)   //找到了一个位置,而且是合法的 
     if(k==n) {  //是不是最后一个皇后,若是则得出一个完整解
     for( i=1;i<=n;i++)
            printf("%d",X[i]);
             printf("\n");
                   } 
      else  {//若不是最后一个皇后,则给下一个皇后找位置
      k=k+1;
      X[k]=0;
          }
   else     
k=k-1; //若是找了全部的列都无法放置某个皇后,则回溯到上一个k的情况 
        } 
} 

void main() { 
        int n; 
        int X[100]; 
        printf("请输入皇后的个数:");
         scanf("%d",&n); 
        printf("问题的解有:"); 
      Nqueens(n,X); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值