用回溯法搜索子集合树的一般框架
void backtrack(int t){ if(t > n) output(x); else{ for(int i = f(n,t); i <= g(n,t);i++){ x[t] = h(i); if(constraint(t) && bound(t)) backtrack(t+1); } } }
不过我这里没考虑算法效率,网上有用公式求解,还有利用位操作进行计算的,有兴趣的可以关注下。
#include <iostream> #include <stdio.h> #include <math.h> using namespace std; void Queen_n(int n); int main() { int n;//N皇后 scanf("%d",&n); Queen_n(n); return 0; } bool place(int *x,int col,int n) { for(int i=0;i<col;i++) { if( x[col] == x[i] || abs(i-col) == abs(x[col]-x[i]) ) return false; } return true; } void BackTracing(int *x,int &sum,int t,int n) { if( t > n-1 ) { sum ++; printf("Column\tRow\n"); for(int i=0;i<n;i++) printf("%3d\t%d\n",i,x[i]); } else { for(int j=0;j<n;j++) { x[t] = j; if( place(x,t,n) ) { BackTracing(x,sum,t+1,n); } } } } void Back_not_resur(int *x,int &sum,int n)//非递归解法 { int i=0,j=0; x[i] = -1; //初始化为-1 while( i<n && i>=0) { x[i] += 1; while(j<n) //如果不能放置,则该列上,继续放在下一行 { x[i] = j; if( !place(x,i,n) ) j++; else break; } if( j<n) { if(i == n-1) //i=n-1,即求解到最后一列,即求解完成 { sum++; printf("Column\tRow\n"); for(int k=0;k<n;k++) printf("%3d\t%d\n",k,x[k]); j++; //继续求解下一个解 //break; //只求一个解,即结束 } else //求解下一列,下一列从第0行开始放置 { i++; x[i] = -1; j=0; } } else //说明该列的所有行都不满足条件,则回溯到前一列,且位置是原来行号的下一行 { j = x[i-1] + 1; i--; } } } void Queen_n(int n) { int *X = new int[n]; int sum = 0; for(int i=0;i<n;i++) X[i] = -1;//X[i]表示第i列上,皇后所在的行号 //BackTracing(X,sum,0,n); //递归方法 Back_not_resur(X,sum,n);//非递归解法 printf("sum = %d\n",sum); delete []X; }