#include <iostream> #include <bitset> using namespace std; #define N 4 /*设置棋盘宽度*/ char pos[N]; /*每一行的这一个棋子放置的位置:0~7*/ bitset<N> stat[N]; /*每一行的空闲位置(除去被行列对角线冲突的位置)*/ bitset<N> mask[N][N]; /*保存回溯过程中以前的状态,因为在对每一行回溯时当时的状态都不一样 所以这个单元的大小是stat的N倍,以便保存N行各自的初始状态*/ int g_count; /*统计有多少种解法*/ void print() /*打印出当前的可行解*/ { int i, j; cout<<endl; for(i=0; i < N; i++) { for(j=0; j < pos[i]; j++) cout<<" - "; cout<<" $ "; for(j=pos[i]+1; j < N; j++) cout<<" - "; cout<<endl; } } void queen(int n) /*皇后问题求解函数*/ { int i, j; if(~stat[n] == 0) /*如果这一行没有空闲位置,这个分支求解失败*/ return; for(i=0; i < N; i++) { if(!stat[n].test(i)) /*test(i)测试第i个bit是否为1,为1返回ture*/ { pos[n] = i; if(n+1 == N) /*找到一个解*/ { print(); g_count++; return; } for(j=n+1; j < N; j++) { mask[n][j] = stat[j]; /*进行新的遍历前保存当前未探测行的空闲状态*/ /*从j=n+1开始保存,前面j=0~n的位置已经保存过了,再保存意义也不大*/ stat[j].set(i); /*纵向标记非空闲位置*/ if(i+j-n < N) stat[j].set(i+j-n); /*正对角线方向标记非空闲位置*/ /*正对角线直线方程:I=kN+b(k=1)->i=n+b->b=i-n==>i-n+j即表示新的I值*/ if(i+n-j >= 0) stat[j].set(i+n-j); /*反对角线方向标记非空闲位置*/ /*反对角线直线方程:I=kN+b(k=-1)->i=-n+b->b=i+n==>-(j)+i+n即表示新的I值*/ } queen(n+1); /*本行探测完毕,进行下一行的探测*/ for(j=n+1; j < N; j++) stat[j] &= mask[n][j]; /*探测失败,回退(返回上一次的状态)*/ } } } int main(int argc, char* argv[]) { int i,j; g_count=0; for(i=0;i<N;i++) stat[i].reset(); for(i=0; i < N; i++) for(j=0; j < N; j++) mask[i][j].reset(); cout<<"result is:"; queen(0); cout<<endl<<"总共有"<<g_count<<"种排法."<<endl<<endl; system("pause"); return 0; }
程序运行结果截图:
原文地址:http://blog.csdn.net/laoniu_c/article/details/38540061