给定一个9x9的网格,有81个正方形方块。我们在一些方块上涂上红色,满足(1)在水平、垂直、主对角线、副对角线方向都没有两个红色方块相邻(2)每行和每列正好包含两个红色方块。请问有多少种不同的染色方案

给定一个9x9的网格,有81个正方形方块。我们在一些方块上涂上红色,同时满足(1)在水平、垂直、主对角线、副对角线方向都没有两个红色方块相邻(2)每行和每列正好包含两个红色方块。请问有多少种不同的染色方案。

这是组合数学中的一个题目,由于目前还没找到合适的数学方法,因此编写了代码来实现。
分别使用的java和python实现。每种编程都采用了普通实现算法以及位运算算法。在实现的过程中也发现,python的运行速度跟java差很多。
供大家参考。如果发现代码实现中有bug,欢迎联系小编,一起探讨。

Java代码

这里是普通的实现

package com.youxin.learnshare.interview.sort;

public class Color {
   


    public static void main(String[] args) {
   

        int n = 9;
        System.out.println(totalNQueens(n));
    }


    public static int totalNQueens(int n) {
   

        int[][] queen = new int[n][n];

        // rowSet[i]表示第 i 行 放了几个
        int[] rowSet = new int[n];
        // colSet[i]表示 第 i 列 放了几个
        int[] colSet = new int[n];

        // 从第 0 行 第 0 列 开始
        return process(queen, 0, 0, rowSet, colSet);

    }


    public static int process(int[][] queen, int row, int col, int[] rowSet, int[] colSet) {
   

        // 达到越界的位置
        if (row == queen.length) {
   
            // 如果合法,返回1种放置的位置
            if (allOk(rowSet, colSet, queen.length)) {
   
                return 1;
            }
            return 0;
        }

        int result = 0;

        for (int i = col; i < queen.length; i++) {
   
            int curOk = isOk(queen, row, i, rowSet, colSet);

            //等于1,说明这一行第一个位置放好了,去 当前行的 下一个位置放第二个
            if (curOk == 1) {
   
                queen[row][i] = 1;
                rowSet[row]++;
                colSet[i]++;
                result += process(queen, row, i + 1, rowSet, colSet);
                // 还原现场 去下一个位置尝试
                queen[row][i] = 0;
                rowSet[row]--;
                colSet[i]--;
            }
            // 说明当前行的2个位置都放好了,去下一行继续
            else if (curOk == 2) {
   
                queen[row][i] = 1;
                rowSet[row]++;
                colSet[i]++;
                result += process(queen, row + 1, 0, rowSet, colSet);
                // 还原现场 去下一个位置尝试
                queen[row][i] = 0;
                rowSet[row]--;
                colSet[i]--;
            }
        }
        return result;
    }


    // 这个方法的返回值表示 如果在这个位置放下后,这个位置是这一行放好的第几个
    // 0 表示这个位置不能放 要去下一个位置尝试
    // 1 表示在这个位置放下后,这一行放置好了一个
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值