给定一个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 表示在这个位置放下后,这一行放置好了一个