慕勒3428872
的替代解决方案isSafe()和class Queen让棋盘成为一个跟踪状态的类采取克隆当前板子状态设置女王并阻止她可以到达的所有领域将克隆向下传递到下一行记住每个皇后的每行列位置placer以下是在闭包中传递的通用求解器。placeRook()通过使用该方法,可以很容易地对车 ( )、骑士 ( placeKnight()) 或主教 ( )使用相同的求解器placeBishop()。请注意,我的解决方案是用 Groovy 编写的,它也在 JVM 上运行,并且非常接近 Java。所以将算法的多汁位翻译成Java应该没有问题。class ChessBoard { int N int lastIndex private boolean[][] board int solutions ChessBoard(int n) { board = new boolean[n][n] N = n lastIndex = n - 1 solutions = 0 this.each { int row, int column -> board[row][column] = true } } ChessBoard(ChessBoard orig) { N = orig.getN() board = new boolean[N][N] lastIndex = N - 1 solutions = 0 this.each { int row, int column -> board[row][column] = orig.getField(row, column) } } void each(Closure c) { (0..lastIndex).each { row -> (0..lastIndex).each { column -> c(row, column) } } } void print() { println " ${'-' * N}" (0..lastIndex).each { row -> print "|" (0..lastIndex).each { column -> print "${board[row][column] ? ' ' : 'X'}" } println "|" } println " ${'-' * N}" } int getN() { return N } int getSolutions() { return solutions } boolean getField(int row, int column) { return board[row][column] } void blockField(int row, int column) { if ((row < 0) || (row > lastIndex)) return if ((column < 0) || (column > lastIndex)) return board[row][column] = false } List<Integer> getFree(int row) { (0..lastIndex).findResults { int column -> board[row][column] ? column : null } } void placeQueen(int row, int column, boolean all = true) { if (all) { (0..lastIndex).each { offset -> blockField(row, offset) // row blockField(offset, column) // column blockField(row + offset, column + offset) // diagonals blockField(row + offset, column - offset) blockField(row - offset, column + offset) blockField(row - offset, column - offset) } } else { blockField(row, column) } } // recursive solver void solve(ChessBoard previous, List<Integer> columns, int row, Closure placer) { List<Integer> free = previous.getFree(row) if (row < lastIndex) { // recurse free.each { column -> ChessBoard work = new ChessBoard(previous) columns[row] = column placer(work, row, column, true) solve(work, columns, row + 1, placer) } } else { // solutions free.each { column -> ChessBoard solution = new ChessBoard(N) columns[row] = column (0..lastIndex).each { placer(solution, it, columns[it], false) } println "Solution #${++solutions}:" solution.print() } } } // start recursion void solve(Closure placer) { List<Integer> columns = [] solve(this, columns, 0, placer) }}board = new ChessBoard(8)board.solve { ChessBoard work, int row, int column, boolean all -> work.placeQueen(row, column, all) }println "Solutions: ${board.getSolutions()}"测试运行:Solution #1: --------|X || X || X|| X || X || X || X || X | --------...Solution #92: --------| X|| X ||X || X || X || X || X || X | --------Solutions: 92如果我没记错的话,对于 8-Queen 问题来说,92 听起来确实是正确的。但是自从我在学校使用 Pascal 中的迭代方法解决这个问题以来已经超过 35 年了 :-)更新改进的解决方案将原始类拆分ChessBoard为跟踪状态和Solver算法皇后、白嘴鸦、主教和骑士的砂矿计算尺寸 1 到 8 的解决方案为结果生成降价表class ChessBoard { private int N private int lastIndex private boolean[][] state ChessBoard(int n) { N = n lastIndex = N - 1 state = new boolean[N][N] (0..lastIndex).each { row -> (0..lastIndex).each { column -> setField(row, column, true) } } } ChessBoard(ChessBoard orig) { N = orig.getN() lastIndex = N - 1 state = new boolean[N][N] (0..lastIndex).each { row -> (0..lastIndex).each { column -> setField(row, column, orig.getField(row, column)) } } } int getN() { return N } boolean getField(int row, int column) { return state[row][column] } void setField(int row, int column, boolean free = false) { if ((row < 0) || (row > lastIndex)) return if ((column < 0) || (column > lastIndex)) return state[row][column] = free } List<Integer> getFree(int row) { (0..lastIndex) .findResults { int column -> getField(row, column) ? column : null } } // for debugging only void print() { println " ${'-' * N}" (0..lastIndex).each { row -> print "|" (0..lastIndex).each { column -> print "${getField(row, column) ? ' ' : 'X'}" } println "|" } println " ${'-' * N}" }}class Solver { private int N private int lastIndex private int solutions private int[] columns Solver(int n) { N = n lastIndex = N - 1 solutions = 0 columns = new int[N] } void printSolution(String label) { solutions++ if (!label) return println "${N}-${label} solution #${solutions}" println " ${'-' * N}" (0..lastIndex).each { row -> int column = columns[row] println "|${' ' * column}X${' ' * (lastIndex - column)}|" } println " ${'-' * N}" } int getSolutions() { return solutions } void placeQueen(ChessBoard board, int row, int column) { // only modify fields from (row+1) downwards (1..(lastIndex - row)).each { offset -> board.setField(row + offset, column) // column board.setField(row + offset, column + offset) // diagonals board.setField(row + offset, column - offset) } } void placeRook(ChessBoard board, int row, int column) { // only modify fields from (row+1) downwards (1..(lastIndex - row)).each { offset -> board.setField(row + offset, column) // column } } void placeBishop(ChessBoard board, int row, int column) { // only modify fields from (row+1) downwards (1..(lastIndex - row)).each { offset -> board.setField(row + offset, column + offset) // diagonals board.setField(row + offset, column - offset) } } static void placeKnight(ChessBoard board, int row, int column) { // only modify fields from (row+1) downwards board.setField(row + 1, column - 2) board.setField(row + 1, column + 2) board.setField(row + 2, column - 1) board.setField(row + 2, column + 1) } // recursive solver void solve(ChessBoard previous, int row, Closure placer, String label) { List<Integer> free = previous.getFree(row) if (row < lastIndex) { // recurse free.each { column -> ChessBoard work = new ChessBoard(previous) columns[row] = column placer(this, work, row, column) solve(work, row + 1, placer, label) } } else { // solutions free.each { column -> columns[row] = column printSolution(label) } } } // start recursion int solve(Closure placer, String label = null) { solve(new ChessBoard(N), 0, placer, label) return solutions }}Map<String, Closure> placers = [ 'Queens': { Solver solver, ChessBoard board, int row, int column -> solver.placeQueen(board, row, column) }, 'Rooks': { Solver solver, ChessBoard board, int row, int column -> solver.placeRook(board, row, column) }, 'Bishops': { Solver solver, ChessBoard board, int row, int column -> solver.placeBishop(board, row, column) }, 'Knights': { Solver solver, ChessBoard board, int row, int column -> solver.placeKnight(board, row, column) },]Map<String, List<Integer>> solutions = [:]// generate solutions up to maxNint maxN = 8boolean print = falseplacers .keySet() .each { String key -> Closure placer = placers[key] List<Integer> results = [] (1..maxN).each { N -> results.push(new Solver(N).solve(placer, print ? key : null)) } solutions[key] = results }// generate markdown table from solutionsList lines = [] (0..maxN).each { lines[it] = [it ?: 'Size'] }[ 'Queens', 'Rooks', 'Bishops', 'Knights',].each { key -> List<Integer> results = solutions[key] lines[0].push(key) (1..maxN).each { lines[it].push(results[it - 1]) }}lines.each { line -> println line.join('|') }return结果表:| Size | Queens | Rooks | Bishops | Knights ||------|--------|-------|---------|---------|| 1 | 1 | 1 | 1 | 1 || 2 | 0 | 2 | 2 | 4 || 3 | 0 | 6 | 5 | 9 || 4 | 2 | 24 | 24 | 52 || 5 | 10 | 120 | 125 | 451 || 6 | 4 | 720 | 796 | 4898 || 7 | 40 | 5040 | 5635 | 67381 || 8 | 92 | 40320 | 48042 | 1131382 ||------|--------|-------|---------|---------|