-
Notifications
You must be signed in to change notification settings - Fork 0
/
Problem_0052_totalNQueens.cc
138 lines (130 loc) · 3 KB
/
Problem_0052_totalNQueens.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <vector>
#include "UnitTest.h"
using namespace std;
class Solution
{
public:
// 用数组表示路径实现的N皇后问题,不推荐
int totalNQueens1(int n)
{
if (n < 1)
{
return 0;
}
vector<int> arr(n);
return f1(0, arr, n);
}
// i : 当前来到的行
// path : 0...i-1行的皇后,都摆在了哪些列
// n : 是几皇后问题
// 返回 : 0...i-1行已经摆完了,i....n-1行可以去尝试的情况下还能找到几种有效的方法
int f1(int i, vector<int>& path, int n)
{
if (i == n)
{
return 1;
}
int ans = 0;
// 每一行都可以在 n 列上尝试
for (int j = 0; j < n; j++)
{
if (check(path, i, j))
{
path[i] = j;
ans += f1(i + 1, path, n);
}
}
return ans;
}
// 当前在i行、j列的位置,摆了一个皇后
// 0...i-1行的皇后状况,path[0...i-1]
// 返回会不会冲突,不会冲突,有效!true
// 会冲突,无效,返回false
bool check(vector<int>& path, int i, int j)
{
for (int k = 0; k < i; k++)
{
if (j == path[k] || std::abs(i - k) == std::abs(j - path[k]))
{
// 1. 前面位置的列跟当前的列在同一列
// 2. 前面位置跟当前位置在同意对角线
return false;
}
}
return true;
}
// 当 n < 32 时,空间优化,位信息替代数组
int totalNQueens2(int n)
{
if (n < 1)
{
return 0;
}
// n = 5
// 1 << 5 = 0...100000 - 1
// limit = 0...011111;
// n = 7
// limit = 0...01111111;
int limit = (1 << n) - 1;
return f2(limit, 0, 0, 0);
}
// limit : 当前是几皇后问题
// 之前皇后的列影响:col
// 之前皇后的右上 -> 左下对角线影响:left
// 之前皇后的左上 -> 右下对角线影响:right
int f2(int limit, int col, int left, int right)
{
if (col == limit)
{
// 所有皇后放完了!
return 1;
}
// 总限制
int ban = col | left | right;
// ~ban : 1可放皇后,0不能放
int candidate = limit & (~ban);
// 放置皇后的尝试!
int place = 0;
// 一共有多少有效的方法
int ans = 0;
while (candidate != 0)
{
// 提取出最右侧的1
// 0 0 1 1 1 0
// 5 4 3 2 1 0
// place :
// 0 0 0 0 1 0
// candidate :
// 0 0 1 1 0 0
// 5 4 3 2 1 0
// place :
// 0 0 0 1 0 0
// candidate :
// 0 0 1 0 0 0
// 5 4 3 2 1 0
// place :
// 0 0 1 0 0 0
// candidate :
// 0 0 0 0 0 0
// 5 4 3 2 1 0
place = candidate & (-candidate);
candidate ^= place;
ans += f2(limit, col | place, (left | place) >> 1, (right | place) << 1);
}
return ans;
}
};
void test()
{
Solution s;
EXPECT_EQ_INT(2, s.totalNQueens1(4));
EXPECT_EQ_INT(1, s.totalNQueens1(1));
EXPECT_EQ_INT(2, s.totalNQueens2(4));
EXPECT_EQ_INT(1, s.totalNQueens2(1));
EXPECT_SUMMARY;
}
int main()
{
test();
return 0;
}