八皇后问题与Las Vegas算法的结合
八皇后问题一直是回溯算法的经典问题。最近在上概率算法,涉及到八皇后问题与Las Vegas算法的结合,花了两天时间写代码,调bug,故特此写下这篇博客以做总结。
传统的回溯法
- 伪代码
- 代码
1 |
|
Las Vegas算法
- Las Vegas算法介绍
- 伪代码
- 代码
1 |
|
问题及改进
- 概况
- 代码:
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
139
140
141
142
143
144
145
using namespace std;
int trycol[100];
bool isPositionOpen(int x, int y, vector<int> col, vector<int> diag45, vector<int> diag135)
{
int tem;
//判断列号
for(tem = 0; tem < col.size(); tem++){
if(col[tem] == y)
return false;
}
//判断45度对角线 45度对角线利用x - y x为行号,y为列号
for(tem = 0; tem < diag45.size(); tem++){
if(diag45[tem] == x-y)
return false;
}
//判断135度对角线
for(tem = 0; tem < diag135.size(); tem++){
if(diag135[tem] == x+y)
return false;
}
return true;
}
void backtrace (int k, vector<int> col, vector<int> diag45, vector<int> diag135, bool &success)
{
stack<int> colStack;
int i = k, j = 1, tem;
bool isOpenFind;
while(i <= QueenNumber){
isOpenFind = false;
//检查当前行i:从当前列j起向后逐列试探,寻找安全序号
while(j <= QueenNumber){
if(isPositionOpen(i, j, col, diag45, diag135)){
isOpenFind = true;
col.push_back(j);
diag45.push_back(i-j);
diag135.push_back(i+j);
break;
}
j++;
}
//找到安全列号
if(isOpenFind){
colStack.push(j);
i++;
j = 1;
}
//未找到安全列号
else{
if(colStack.empty()){
success = false;
return;
}
j = colStack.top();
colStack.pop();
i--;
for (vector<int>::iterator iter = col.begin(); iter != col.end(); ++iter){
if(*iter == j){
col.erase(iter);
break;
}
}
for (vector<int>::iterator iter = diag45.begin(); iter != diag45.end(); ++iter){
if(*iter == i-j){
diag45.erase(iter);
break;
}
}
for (vector<int>::iterator iter = diag135.begin(); iter != diag135.end(); ++iter){
if(*iter == i+j){
diag135.erase(iter);
break;
}
}
j++;
}
}
success = true;
for(tem=QueenNumber; tem>=k; tem--){
trycol[tem] = colStack.top();
colStack.pop();
}
}
void QueenLV(bool &success)
{
vector<int> col, diag45, diag135;
col.clear();
diag45.clear();
diag135.clear();
int k = 0, nb, i, j;
random_device rd;
mt19937 gen(rd());
do{
nb = 0;
for(i = 1; i <= QueenNumber; i++){
if(isPositionOpen(k+1, i, col, diag45, diag135)){
nb++;
uniform_int_distribution<> dis(1, nb);
if(dis(gen) == 1){
j = i;
}
}
}
if(nb > 0){
k++;
trycol[k] = j;
col.push_back(j);
diag45.push_back(k-j);
diag135.push_back(k+j);
}
}while(nb !=0 && k != stepVegas);
if(nb == 0){
success = false;
}
else{
backtrace(stepVegas+1, col, diag45, diag135, success);
}
}
int main()
{
bool success;
do{
QueenLV(success);
}while(!success);
if(success){
for(int i=1; i<= QueenNumber; i++){
cout<<trycol[i]<<endl;
}
}
else{
cout<<"hello world!\n"<<endl;
}
getchar();
return 0;
}
总结
Las Vegas算法与回溯法的结合往往能够提高程序的运行效率。Las Vegas算法虽然为随机算法,但是相较于确定性算法,却提高了程序的效率,这是一个值得借鉴的地方。以前接触的往往都是确定性算法,在以后的编码过程中,可以考虑加入随机算法,也许会获得意想不到的结果。