回溯经典-n皇后问题

题目大意:

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

http://zh.wikipedia.org/wiki/八皇后问题 在维基百科上有详细的描述。

 

算法思路:

递归方法和非递归方法实现如下:

/* 递归方法实现,输入n,输出所有的可能的皇后分布 */ #include <iostream> #define MAXN 105 using namespace std; int array[MAXN] = {0}; int outarray[MAXN][MAXN] = {0}; int N; int num = 0; //输出结果 void output() { cout << num << endl; for(int i = 0; i< N; i++) { for(int j = 0; j< N; j++) { cout << '|'; outarray[i][j]? cout << 'Q': cout << ' '; } cout <<'|'<< endl; } cout << endl; } //通过与前面0->x-1个皇后比较,判断(x,y)位置是否安全 bool place(int x, int y) { for(int i = 0; i < x; i++) { int j = array[i]; if(i == x || j == y) return false; //同行,同列都是不可以的 if(x-y == i-j || x+y == i+j) return false; //对角线上也是不允许的 } return true; } //处在第x行时的状态,这是回溯的主线,从0行到n-1行为止 void nqueue(int x) { if(x >= N) //当到达最后一行之后,输出n个皇后的分布情况 { num++; output(); } else //当还没有到达最后一行之时,继续往下一行递归,枚举y所有的可能情况 { for(int y = 0; y < N; y++) { array[x] = y; outarray[x][y] = 1; if(place(x, y)) nqueue(x+1); outarray[x][y] = 0; } } } int main() { cin >> N; nqueue(0); return 0; }  

 

 

 

//迭代实现: #include <stdio.h> #include <stdlib.h> #define N 8 int x[N]; int sum; bool place(int i) { int j=0; for(j =0;j<i;j++) if(abs(x[i]-x[j]) == abs(i-j)|| x[j] == x[i]) return false; return true; } void queen() { x[0]=-1;//初始化第一个皇后的坐标,在第一行第一列 int k = 0;//表示列号 while(k>=0) { x[k]+=1;//此时对于第k个皇后,列号向右移动,表示,当回溯到这一层时0~x[k]-1已经探索过了,接着往后探索 while(x[k]<N && !place(k)) x[k]++;//对于第k个皇后,找到一个合适的位置 if(x[k]<N) { if(k==N-1) sum ++;//如果k已经是最后一个皇后,则找到了一个方案 else// 否则,继续探索下一个皇后 { k++; x[k] = -1; } } else//对于第k个皇后,没有找到一个合适的位置,这相对于搜索树的第k层,于是对于这个节点的子树不再搜索,回溯到上一层 k--; } } int main() { queen(); printf("sum = %d/n",sum); }  

 

参考:

http://zh.wikipedia.org/wiki/八皇后问题

http://blog.csdn.net/clearriver/archive/2009/06/21/4287283.aspx

http://www.cppblog.com/3522021224/archive/2007/06/21/26785.html

你可能感兴趣的:(算法,output)