八皇后问题

八皇后问题

参考视频链接

这里我要感谢b站小姐姐的讲解,讲的真的超棒的,我能顺利地做出来就靠这个视频了。

  1. 问题解决的关键点

    1. 回溯
    2. 棋盘存储
    3. 攻击范围
  2. dfs核心递归函数

    k==n 表示找到一组解 打印

    在一层循环判断是否可以放置皇后,如果可以进行以下操作(按列):

    1. 备份attack数组(备份后,最后恢复)
    2. 标记该位置为Q(2. 存储位置)queue[k][i]='Q' (仅改变一个地方,最后直接改回来)
    3. 上一步放置了皇后,所以更新attack数组
    4. 递归试探k+1行的皇后位置(按行)
    5. 递归完成后,恢复attack数组和 queue[k][i]='.'
  3. 代码总览

    /* 八皇后问题 */
    #include<stdio.h>
    int ack[10][10];
    char que[10][10];
    int cnt=0;
    
    void init (int n);//初始化
    void print(int n);//数组的打印
    void copy(int a[10][10],int b[10][10],int n);//把a数组拷贝到b数组
    void dfs(int k,int n);//核心递归算法
    void update_ack(int x,int y,int n);//更新ack数组
    int main()
    {
        int n;
        scanf("%d",&n);
        init(n);
    
        dfs(0,n);
    
        printf("cnt = %d\n",cnt);
        return 0;
    }
    
    void init (int n){
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                ack[i][j]=0;
                que[i][j]='.';
            }
    }
    void print(int n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++)
                printf("%c ",que[i][j]);
            printf("\n");
        }
        printf("\n");
    }
    void dfs(int k,int n){
    // k==n 表示找到一组解  打印
        if(k==n){
            print(n);
            cnt++;
            return;
        }
        for(int i=0;i<n;i++){
        // 在一层循环判断是否可以放置皇后,如果可以进行以下操作(按列):
            if(ack[k][i]==0){
            // 1. 备份attack数组(备份后,最后恢复)
                int tmp[10][10];
                copy(ack,tmp,n);
            // 2. 标记该位置为Q(2. 存储位置)`queen[k][i]='Q'` (仅改变一个地方,最后直接改回来)
                que[k][i]='Q';
            // 3. 上一步放置了皇后,所以更新attack数组 
                update_ack(k,i,n);
            // 4.  递归试探k+1行的皇后位置(按行)
                dfs(k+1,n);
            // 5. 递归完成后,恢复attack数组和 `queen[k][i]='.' `
                copy(tmp,ack,n);
                que[k][i]='.';
            }
        }
    }
    void copy(int a[10][10],int b[10][10],int n){
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                b[i][j]=a[i][j];
    }
    void update_ack(int x,int y,int n){
        int dx[]={-1,-1,-1,0, 1, 1, 1, 0};
        int dy[]={-1,0, 1, 1, 1, 0,-1,-1};
        ack[x][y]=1;
    
        for(int i=1;i<=n-1;i++)//从1延伸到n-1的距离
            for(int j=0;j<8;j++){//从八个方向延伸
                int nx=x+i*dx[j];
                int ny=y+i*dy[j];
    
                if(nx>=0&&nx<n&&ny>=0&&ny<n)
                    ack[nx][ny]=1;
            }
    }
    
  4. 测试结果

在这里插入图片描述
在这里插入图片描述

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值