最近程序设计技术与方法课程实验有一个作业——八皇后问题
首先八皇后问题的解释:
在一个8乘8的棋盘上有八个皇后,处于同一行,同一列,同一斜线的皇后会打架,现在就是求出如何摆放这八个皇后才能使得皇后不打架。
思考:
因为这些皇后不能不能处于同一行,所以这个棋盘的八行各要放置一个皇后,完全可以每次只确定某一行皇后的放置本行的第几列。(通俗来讲就是第一次确定第一行的皇后放在哪里,第二次确定第二行的皇后放在哪里以此类推)接下来就是重点了,认真看!
用一个8bit的数据row来记录已经放置过的列(比如2(对应的是00000010)表示的是第7列已经放置过皇后,因为行是按照顺序放置的这也表明第一行放置了皇后),然后用两个8bit的数据r,l,来记录在下一行会被前面几行存在的皇后斜向左或者斜向右打架的位置。通过(r | l | row)位运算可以得到下一行不能放置的位置。显然通过~运算得到的就是可以放置的位置。每次取出最右边的位置放置,进行递归。下面表述不太清除看代码(代码针对的是n皇后问题n为8时候就是八皇后问题):
/*
位运算试探法:
每次试探一行用有n个bit的数据表示,row来存放已经放过的列
l用来存放与前面所有行不兼容的左斜杠,r是右斜杠
*/
#include<iostream>
#include<ctime>
long count_ = 0;
//l存放的是左斜杠可以会打架的皇后,r存放的是右斜杠会打架的皇后,row存放的是已经放了皇后的列
void queen(long row,long l,long r,long answer) {
if (row == answer) {//如果n列放满了,也就是满足条件了。那么就统计。
count_++;
}
else {
long pos = (answer& ~(r | l | row));//求出这一行中能放置的所有列的位置。
while (pos) {//只要还能放就放,不能放就回溯
long p = pos& -pos;//求出最右边的一个可以放在row上的位置
queen(row | p, (l|p)<<1, (r|p)>>1,answer);
pos = pos ^ p;//减去已经放置过的位置
}
}
}
int main(void) {
clock_t c0 = clock();
long answer = 0;
int n;
std::cout << "please input the value of n:"<<std::endl;
std::cin >> n;
for (int i = 0; i < n; i++)//得到结果标志
{
answer = answer | (1 << i);
}
//或者answer << n - 1;
queen(0, 0, 0, answer);
clock_t c1 = clock();
std::cout << count_ << std::endl;
int tim = (c1 - c0) / CLOCKS_PER_SEC;
std::cout << "计算这个问题一共用了"<<tim <<"秒。"<< std::endl;
return 0;
}
这里是八皇后的问题运行结果:移动用了2秒,92种情况。