回溯法解决N皇后问题(以四皇后为例)

以4皇后为例,其他的N皇后问题以此类推。所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子。在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平、竖直、以及45度斜线上都不能出现皇后的棋子,例子

要求编程求出符合要求的情况的个数。四皇后问题有很多种解法,这里主要介绍一种经典的解决方法:回溯法

回溯法的基本思想是:可以构建出一棵解空间树,通过探索这棵解空间树,可以得到四皇后问题的一种或几种解。这样的解空间树有四棵

在如上图所示的4×4的棋盘上,按列来摆放棋子,首先因为皇后棋子不能在同一列,所以先排除有2个或2个以上的棋子在同一列的情况,所以第一个棋子在第一列有4种摆放方法(第1列第1行,第1列第2行,第1列第3行,第1列第4行),同样第二个棋子在第二列有4种,同样第三个棋子在第三列有4种,同样第四个棋子在第四列有4种,所以进行简单的排除不在同一列的情况后,还有4×4×4×4=256种可能,但是在这256种可能里,依然存在比如棋子在同一行,或在45度斜线上的情况出现。另一个角度思考,所有的满足四皇后问题的摆放方式一定都存在于这256种情况之中。简单的理解就是:这256种棋盘局面包含了所有满足4皇后问题的解,但是不包含全部的棋盘局面。

#include<stdio.h>
#define maxn 4 
int count = 0;

int isCorrect(int i, int j, int (*Q)[maxn])
{
    int s, t;
    for(s=i,t=0; t<maxn; t++)
        if(Q[s][t]==1 && t!=j)
            return 0;//判断行
    for(t=j,s=0; s<maxn; s++)
        if(Q[s][t]==1 && s!=i)
            return 0;//判断列
    for(s=i-1,t=j-1; s>=0&&t>=0; s--,t--)
        if(Q[s][t]==1)
            return 0;//判断左上方
    for(s=i+1,t=j+1; s<maxn&&t<maxn;s++,t++)
        if(Q[s][t]==1)
            return 0;//判断右下方
    for(s=i-1,t=j+1; s>=0&&t<maxn; s--,t++)
        if(Q[s][t]==1)
            return 0;//判断右上方
    for(s=i+1,t=j-1; s<maxn&&t>=0; s++,t--)
        if(Q[s][t]==1)
            return 0;//判断左下方

    return 1;//否则返回
}

void Queue(int j, int (*Q)[maxn])
{
    int i,k;
    if(j==maxn)  //递归结束条件
    {
        for(i=0; i<maxn; i++) //得到一个解,在屏幕上显示
        {
            for(k=0; k<maxn; k++)
                printf("%d ", Q[i][k]);
            printf("\n");
        }
        printf("\n");
        count++;
        return ;
    }
    for(i=0; i<maxn; i++){
        if(isCorrect(i, j, Q))//如果Q[i][j]可以放置皇后
        {
            Q[i][j]=1;      //放置皇后
            Queue(j+1, Q);   //递归深度优先搜索解空间树(逐列行循环)
            Q[i][j]=0;     //这句代码就是实现回溯到上一层
        }
    }
}

int main()
{
    int Q[maxn][maxn];
    int i, j;
    for(i=0; i<maxn; i++)
        for(j=0; j<maxn; j++)
            Q[i][j] = 0;
            
    Queue(0, Q);
    printf("The number of the answers are %d\n", count);
    return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值