N 皇后 II - 位图

var (
	N int
	ans int
)
 
func totalNQueens(n int) int {
	N = n
	ans = 0
 
	backtracking(0, 0, 0 ,0)
 
	return ans
}
 
// curN 当前列
// columns 位图(列)
// diagonals1 int 位图(对角线:左上到右下)
// diagonals2 int 位图(对角线:右上到左下)
func backtracking(curN, columns, diagonals1, diagonals2 int) {
	if curN == N {
		ans++
		return
	}
 
	availablePositions := (1 << N - 1) &^ (columns | diagonals1 | diagonals2)
	// ((1 << N) - 1) & (^(columns | diagonals1 | diagonals2))
	for availablePositions > 0 {
		// Brian Kernighan 算法:提取出二进制状态中最右侧的 1
		pos := availablePositions & -availablePositions
		backtracking(curN + 1, columns | pos, (diagonals1 | pos) << 1, (diagonals2 | pos) >> 1)
		availablePositions &^= pos // 移除比特位
	}
}

curN 也不必要,可以用位运算代替:

var (
	ans int
	limit int // 需要放置皇后的位置
)
 
func totalNQueens(n int) int {
	ans = 0
	// 最小 n 位是 1,其他位是 0
	limit = 1 << n - 1
 
	backtracking(0, 0 ,0)
 
	return ans
}
 
// columns 位图(列)
// diagonals1 int 位图(对角线:左上到右下)
// diagonals2 int 位图(对角线:右上到左下)
func backtracking(columns, diagonals1, diagonals2 int) {
	if columns == limit { // 需要放置皇后的位置都放好了皇后
		ans++
		return
	}
 
	availablePositions := limit &^ (columns | diagonals1 | diagonals2)
	// ((1 << N) - 1) & (^(columns | diagonals1 | diagonals2))
	for availablePositions > 0 {
		// Brian Kernighan 算法:提取出二进制状态中最右侧的 1
		pos := availablePositions & -availablePositions
		backtracking(columns | pos, (diagonals1 | pos) << 1, (diagonals2 | pos) >> 1)
		availablePositions &^= pos // 移除比特位
	}
}

位运算知识