• n皇后问题与2n皇后问题


    n皇后问题
    问题描述:
      如何能够在 n×n 的棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后 (任两个皇后都不能处于同一条横行、纵行或斜线上)
    结题思路:
      可采用深度优先算法,将棋盘看成一个n*n的地图,每层有n个顶点,共有n层。然后套用dfs,每一层要判断与前面的皇后会不会冲突,如果不会,则可以放置皇后(可以走这个顶点),直到最后一层,将解决方案数量加一就行了。
    注:用一维数组 queen[10] 即可代表女皇的横竖坐标,下标为第几行,结果则为第几列。
      当 abs(queen[i] - queen[n]) == abs(n - i) 时说明在一个斜线上(y2-y1==x2-x1 说明两点成45°角)
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    
    
    int queen[10], sum=0;
    int Max;
    //此函数用于判断皇后当前皇后是否可以放在此位置
    int PLACE(int n) /* 检查当前列能否放置皇后 */
    {//abs(queen[i] - queen[n]) == abs(n - i)用于约束元素不能再同一行且不能再同一条斜线上
        int i;
        for(i = 1; i < n; i++) /* 检查横排和对角线上是否可以放置皇后 */
        {
            if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == abs(n - i))
            {
                return 0;
            }
        }
        return 1;
    }
    
    //核心函数,回溯法的思想
    void NQUEENS(int n) /* 回溯尝试皇后位置,n为横坐标 */
    {
        int i;
        for(i = 0; i < Max; i++)
        {
            queen[n] = i;
            if(PLACE(n))
            {
                if(n == Max)
                {
                   sum++;
                }
                else
                {
                    NQUEENS(n + 1); 
                }
            }
        }
    }
    
    int main()
    {
        cin>>Max;
        NQUEENS(1); /* 从横坐标为0开始依次尝试 */
        printf("总共的解法有%d种
    ", sum);
    
        return 0;
    }
    
    2n皇后:
    问题描述
      给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
    输入格式
      输入的第一行为一个整数n,表示棋盘的大小。
      接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
    输出格式
      输出一个整数,表示总共有多少种放法。
    样例输入
    4
    1 1 1 1
    1 1 1 1
    1 1 1 1
    1 1 1 1
    样例输出
    2
    样例输入
    4
    1 0 1 1
    1 1 1 1
    1 1 1 1
    1 1 1 1
    样例输出
    0
     
    知道n皇后怎么解后2n皇后就容易理解了。只要在白皇后摆放好后再用同样的方式摆放黑皇后即可,不过也要注意白皇后不能和黑皇后摆在同一个位置(i!=wqueen[n])
    以及map上值为0不能摆放皇后,加上这两个两个条件即可。
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    
    int bqueen[10], wqueen[10], sum=0;     // Max为棋盘最大坐标 
    int Max;
    int map[10][10];                    //map用于判断白皇后是否已经放置(2) 或 该位置可以放置(1) 或 不可放置(0)
    
    
    int w_place(int n) /* 检查当前列能否放置白皇后 */
    {
        int i;                    //第i个皇后 
        for(i = 0; i < n; i++)     //检查横排和对角线上是否可以放置皇后
        {
            if(wqueen[i]==wqueen[n] || abs(wqueen[i]-wqueen[n])==abs(n-i))
            {
                return 0;
            }
        }
        return 1;
    }
    
    int b_place(int n)
    {
        int i;                    //第i个皇后 
        for(i = 0; i < n; i++)     //检查横排和对角线上是否可以放置皇后
        {
            if(bqueen[i]==bqueen[n] || abs(bqueen[i]-bqueen[n])==abs(n-i))
            {
                return 0;
            }
        }
        return 1;
    }
    
    
    void b_queen(int n)
    {
        int i;
        for(i=0; i<Max; i++)
        {
            if(map[n][i])
            {
                bqueen[n] = i;
                if(b_place(n) && i!=wqueen[n])    //判断可以摆在该坐标 
                {
                    if(n==Max-1)    //判断是否是最后一个皇后(最后一行) 
                    {
                        sum++; 
                    } 
                    else
                    {
                        b_queen(n+1);
                    }
                }
            }
        }
    }
    
    
    void w_queen(int n) /* 回溯尝试皇后位置,n为横坐标 */
    {
        int i;
        for(i=0; i<Max; i++)
        {
            if(map[n][i])
            {
                wqueen[n] = i;
                if(w_place(n))
                {
                    if(n==Max-1)
                    {
                        b_queen(0);
                    }
                    else
                    {
                        w_queen(n+1);
                    }
                }
            }
        }
    }
    
    int main()
    {
        cin>>Max;
        for(int i=0; i<Max; i++)
            for(int j=0; j<Max; j++)
                scanf("%d", &map[i][j]);        
        w_queen(0);
        printf("%d
    ", sum);
    
        return 0;
    }
     
  • 相关阅读:
    智能佳 金刚足球机器人 竞赛机器人 智能机器人
    DIY小能手|别买电动滑板车了,咱做一台吧
    !!2016/02/22——当日买入——事后追悔,总结经验,忘记了买票的初衷!
    20160222深夜 支撑与阻力的问题,突破要不要买,回踩要不要接
    2016/2/4——昨天操作错误
    C语言 · 瓷砖铺放
    C语言 · 字符串编辑
    C语言 · 比较字符串
    C语言 · 3000米排名预测
    C语言 · 陶陶摘苹果2
  • 原文地址:https://www.cnblogs.com/kamicoder/p/8535458.html
Copyright © 2020-2023  润新知