forked from chenshuo/recipes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
nqueens_opt_mt.cc
110 lines (98 loc) · 2.3 KB
/
nqueens_opt_mt.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
#include <algorithm>
#include <atomic>
#include <thread>
#include <vector>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/time.h>
double now()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec / 1000000.0;
}
struct BackTracking
{
static const int kMaxQueens = 20;
const int N;
const uint32_t mask;
int64_t count;
BackTracking(int nqueens)
: N(nqueens), mask(~((1 << N) - 1)), count(0)
{
assert(0 < N && N <= kMaxQueens);
}
void search(const int row,
const uint32_t columns,
const uint32_t diagnoal,
const uint32_t antidiagnoal)
{
uint32_t avail = ~(columns | diagnoal | antidiagnoal | mask);
while (avail) {
const int i = __builtin_ctz(avail); // counting trailing zeros
avail &= avail-1;
if (row == N - 1) {
++count;
} else {
const uint32_t m = 1 << i;
search(row+1,
columns | m,
(diagnoal | m) >> 1,
(antidiagnoal | m) << 1);
}
}
}
};
int64_t backtrackingsub(int N, int i)
{
const int row = 0;
const uint32_t m = 1 << i;
BackTracking bt(N);
bt.search(row+1, m, m >> 1, m << 1);
return bt.count;
}
// verify task splitting
int64_t backtracking(int N)
{
int64_t total = 0;
for (int i = 0; i < N/2; ++i) {
total += backtrackingsub(N, i);
}
total *= 2;
if (N % 2 == 1) {
total += backtrackingsub(N, N/2);
}
return total;
}
void backtracking_thr(std::atomic<int64_t>* total, int N, int i)
{
// printf("%d %d\n", i, backtrackingsub(N, i));
if (N % 2 == 1 && i == N / 2) {
total->fetch_add(backtrackingsub(N, i));
} else {
total->fetch_add(2*backtrackingsub(N, i));
}
}
int64_t backtracking_mt(int N)
{
std::atomic<int64_t> total(0);
std::vector<std::thread> threads;
for (int i = 0; i < (N+1)/2; ++i) {
threads.push_back(std::thread(backtracking_thr, &total, N, i));
}
for (auto& thr : threads) {
thr.join();
}
return total;
}
int main(int argc, char* argv[])
{
int nqueens = argc > 1 ? atoi(argv[1]) : 8;
double start = now();
int64_t solutions = backtracking_mt(nqueens);
double end = now();
printf("%ld solutions of %d queens puzzle.\n", solutions, nqueens);
printf("%f seconds.\n", end - start);
}