八皇后(Swift)

255 阅读7分钟

这里n过大,递归,可能会堆栈溢出

尾递归优化参考: www.ruanyifeng.com/blog/2015/0…

RxSwift中 Concat 尾递归优化的使用(详见源码实现):reactivex.io/documentati…


var count = 0

/// n * n 的矩阵
let n = 8

/// 是否为最后一行
let isLastRow = n - 1

/// 在每一行的位置
var datas: [Int] = [Int](repeating: -1, count: n)

/// 当前位置是否符合
func check(x: Int, y: Int) -> Bool {
    /// 当前是第一行不用判断
    guard y > 0 else {
        return true
    }
    /// 遍历前面已经确定的行
    for row in 0..<y {
        let num = datas[row]
        guard (0..<n).contains(num) else {
            return false
        }
        if x == num {
            return false
        }
        if abs(x - num) == y - row {
            return false
        }
    }
    if y == n - 1 {
        count += 1
        print("符合条件:\(datas)")
        print("符合条件个数:\(count)")
    }
    return true
}

/// 该行棋子位置后移一位,找到所有的可能
func start(currentRow: Int = 0) {
    // 行不在[0,n) return
    guard (0..<n).contains(currentRow) else {
        return
    }
    // 在一行中的最后一个格
    if datas[currentRow] == n - 1 {
        start(currentRow: currentRow - 1)
        return
    }
    // 将该行位置后移一位
    var num = datas[currentRow]
    num += 1
    datas[currentRow] = num
    
    for row in currentRow..<n {
        if row == currentRow {
            if !check(x: num, y: currentRow) {
                start(currentRow: currentRow)
                return
            }
            else {
                if row == isLastRow {
                    start(currentRow: currentRow)
                    return
                }
            }
            continue
        }
        var hasPoint = false
        for item in 0..<n {
            datas[row] = item
            hasPoint = check(x: item, y: row)
            // 找到合适的点,并且不是最后一行,往下移一行
            if hasPoint, row != isLastRow {
                datas[row + 1] = -1
                start(currentRow: row + 1)
                return
            }
            // 该行没有合适的点,往上移一行 + 1
            if !hasPoint, item == n - 1 {
                start(currentRow: row - 1)
                return
            }
            //遍历完最后一个点,往上移一行
            if row == isLastRow, item == n - 1 {
                start(currentRow: row - 1)
                return
            }
        }
    }
}

start()

打印结果:

符合条件:[0, 4, 7, 5, 2, 6, 1, 3]
符合条件个数:1
符合条件:[0, 5, 7, 2, 6, 3, 1, 4]
符合条件个数:2
符合条件:[0, 6, 3, 5, 7, 1, 4, 2]
符合条件个数:3
符合条件:[0, 6, 4, 7, 1, 3, 5, 2]
符合条件个数:4
符合条件:[1, 3, 5, 7, 2, 0, 6, 4]
符合条件个数:5
符合条件:[1, 4, 6, 0, 2, 7, 5, 3]
符合条件个数:6
符合条件:[1, 4, 6, 3, 0, 7, 5, 2]
符合条件个数:7
符合条件:[1, 5, 0, 6, 3, 7, 2, 4]
符合条件个数:8
符合条件:[1, 5, 7, 2, 0, 3, 6, 4]
符合条件个数:9
符合条件:[1, 6, 2, 5, 7, 4, 0, 3]
符合条件个数:10
符合条件:[1, 6, 4, 7, 0, 3, 5, 2]
符合条件个数:11
符合条件:[1, 7, 5, 0, 2, 4, 6, 3]
符合条件个数:12
符合条件:[2, 0, 6, 4, 7, 1, 3, 5]
符合条件个数:13
符合条件:[2, 4, 1, 7, 0, 6, 3, 5]
符合条件个数:14
符合条件:[2, 4, 1, 7, 5, 3, 6, 0]
符合条件个数:15
符合条件:[2, 4, 6, 0, 3, 1, 7, 5]
符合条件个数:16
符合条件:[2, 4, 7, 3, 0, 6, 1, 5]
符合条件个数:17
符合条件:[2, 5, 1, 4, 7, 0, 6, 3]
符合条件个数:18
符合条件:[2, 5, 1, 6, 0, 3, 7, 4]
符合条件个数:19
符合条件:[2, 5, 1, 6, 4, 0, 7, 3]
符合条件个数:20
符合条件:[2, 5, 3, 0, 7, 4, 6, 1]
符合条件个数:21
符合条件:[2, 5, 3, 1, 7, 4, 6, 0]
符合条件个数:22
符合条件:[2, 5, 7, 0, 3, 6, 4, 1]
符合条件个数:23
符合条件:[2, 5, 7, 0, 4, 6, 1, 3]
符合条件个数:24
符合条件:[2, 5, 7, 1, 3, 0, 6, 4]
符合条件个数:25
符合条件:[2, 6, 1, 7, 4, 0, 3, 5]
符合条件个数:26
符合条件:[2, 6, 1, 7, 5, 3, 0, 4]
符合条件个数:27
符合条件:[2, 7, 3, 6, 0, 5, 1, 4]
符合条件个数:28
符合条件:[3, 0, 4, 7, 1, 6, 2, 5]
符合条件个数:29
符合条件:[3, 0, 4, 7, 5, 2, 6, 1]
符合条件个数:30
符合条件:[3, 1, 4, 7, 5, 0, 2, 6]
符合条件个数:31
符合条件:[3, 1, 6, 2, 5, 7, 0, 4]
符合条件个数:32
符合条件:[3, 1, 6, 2, 5, 7, 4, 0]
符合条件个数:33
符合条件:[3, 1, 6, 4, 0, 7, 5, 2]
符合条件个数:34
符合条件:[3, 1, 7, 4, 6, 0, 2, 5]
符合条件个数:35
符合条件:[3, 1, 7, 5, 0, 2, 4, 6]
符合条件个数:36
符合条件:[3, 5, 0, 4, 1, 7, 2, 6]
符合条件个数:37
符合条件:[3, 5, 7, 1, 6, 0, 2, 4]
符合条件个数:38
符合条件:[3, 5, 7, 2, 0, 6, 4, 1]
符合条件个数:39
符合条件:[3, 6, 0, 7, 4, 1, 5, 2]
符合条件个数:40
符合条件:[3, 6, 2, 7, 1, 4, 0, 5]
符合条件个数:41
符合条件:[3, 6, 4, 1, 5, 0, 2, 7]
符合条件个数:42
符合条件:[3, 6, 4, 2, 0, 5, 7, 1]
符合条件个数:43
符合条件:[3, 7, 0, 2, 5, 1, 6, 4]
符合条件个数:44
符合条件:[3, 7, 0, 4, 6, 1, 5, 2]
符合条件个数:45
符合条件:[3, 7, 4, 2, 0, 6, 1, 5]
符合条件个数:46
符合条件:[4, 0, 3, 5, 7, 1, 6, 2]
符合条件个数:47
符合条件:[4, 0, 7, 3, 1, 6, 2, 5]
符合条件个数:48
符合条件:[4, 0, 7, 5, 2, 6, 1, 3]
符合条件个数:49
符合条件:[4, 1, 3, 5, 7, 2, 0, 6]
符合条件个数:50
符合条件:[4, 1, 3, 6, 2, 7, 5, 0]
符合条件个数:51
符合条件:[4, 1, 5, 0, 6, 3, 7, 2]
符合条件个数:52
符合条件:[4, 1, 7, 0, 3, 6, 2, 5]
符合条件个数:53
符合条件:[4, 2, 0, 5, 7, 1, 3, 6]
符合条件个数:54
符合条件:[4, 2, 0, 6, 1, 7, 5, 3]
符合条件个数:55
符合条件:[4, 2, 7, 3, 6, 0, 5, 1]
符合条件个数:56
符合条件:[4, 6, 0, 2, 7, 5, 3, 1]
符合条件个数:57
符合条件:[4, 6, 0, 3, 1, 7, 5, 2]
符合条件个数:58
符合条件:[4, 6, 1, 3, 7, 0, 2, 5]
符合条件个数:59
符合条件:[4, 6, 1, 5, 2, 0, 3, 7]
符合条件个数:60
符合条件:[4, 6, 1, 5, 2, 0, 7, 3]
符合条件个数:61
符合条件:[4, 6, 3, 0, 2, 7, 5, 1]
符合条件个数:62
符合条件:[4, 7, 3, 0, 2, 5, 1, 6]
符合条件个数:63
符合条件:[4, 7, 3, 0, 6, 1, 5, 2]
符合条件个数:64
符合条件:[5, 0, 4, 1, 7, 2, 6, 3]
符合条件个数:65
符合条件:[5, 1, 6, 0, 2, 4, 7, 3]
符合条件个数:66
符合条件:[5, 1, 6, 0, 3, 7, 4, 2]
符合条件个数:67
符合条件:[5, 2, 0, 6, 4, 7, 1, 3]
符合条件个数:68
符合条件:[5, 2, 0, 7, 3, 1, 6, 4]
符合条件个数:69
符合条件:[5, 2, 0, 7, 4, 1, 3, 6]
符合条件个数:70
符合条件:[5, 2, 4, 6, 0, 3, 1, 7]
符合条件个数:71
符合条件:[5, 2, 4, 7, 0, 3, 1, 6]
符合条件个数:72
符合条件:[5, 2, 6, 1, 3, 7, 0, 4]
符合条件个数:73
符合条件:[5, 2, 6, 1, 7, 4, 0, 3]
符合条件个数:74
符合条件:[5, 2, 6, 3, 0, 7, 1, 4]
符合条件个数:75
符合条件:[5, 3, 0, 4, 7, 1, 6, 2]
符合条件个数:76
符合条件:[5, 3, 1, 7, 4, 6, 0, 2]
符合条件个数:77
符合条件:[5, 3, 6, 0, 2, 4, 1, 7]
符合条件个数:78
符合条件:[5, 3, 6, 0, 7, 1, 4, 2]
符合条件个数:79
符合条件:[5, 7, 1, 3, 0, 6, 4, 2]
符合条件个数:80
符合条件:[6, 0, 2, 7, 5, 3, 1, 4]
符合条件个数:81
符合条件:[6, 1, 3, 0, 7, 4, 2, 5]
符合条件个数:82
符合条件:[6, 1, 5, 2, 0, 3, 7, 4]
符合条件个数:83
符合条件:[6, 2, 0, 5, 7, 4, 1, 3]
符合条件个数:84
符合条件:[6, 2, 7, 1, 4, 0, 5, 3]
符合条件个数:85
符合条件:[6, 3, 1, 4, 7, 0, 2, 5]
符合条件个数:86
符合条件:[6, 3, 1, 7, 5, 0, 2, 4]
符合条件个数:87
符合条件:[6, 4, 2, 0, 5, 7, 1, 3]
符合条件个数:88
符合条件:[7, 1, 3, 0, 6, 4, 2, 5]
符合条件个数:89
符合条件:[7, 1, 4, 2, 0, 6, 3, 5]
符合条件个数:90
符合条件:[7, 2, 0, 5, 1, 4, 6, 3]
符合条件个数:91
符合条件:[7, 3, 0, 2, 5, 1, 6, 4]
符合条件个数:92