八皇后问题---详解---参考<<紫书>>

在一个8*8的棋盘上  放置八个皇后 , 使得他们互相不攻击(皇后攻击范围为 同行同列同对角线) ,

方法一 : 

从64个格子中 选一个子集 , 使得 " 子集 中恰好有八个元素 , 且任意选出的两个格子都不是同一行,同一列同,一对角线"  , 这是子集枚举问题 , 然而 , 64个格子的自己有2^64个   ,   所需处理数据过大 !

方法二: 

从64个格子中 选八个格子 , 称为组合生成问题 , 根据组合数学 有 4.426*10^9中方案 , 虽然比第一种好 , 但是然并卵 .

---------------------------我是分割线-------------------------------------- 

经过思考你会不难发现下面一种方法 , 每一行每一列恰好会放一个皇后 , 所以可以从第一行开始放 , 然后考虑第二行 , 依次进行 下去 !

这样就变成了全排列生成问题 , 这样的排列有 8! = 40320个 , 枚举量不会超过该数字 

然而 如果每次都枚举这么多次的话   也会超时的 , 所以我们可以采用回溯的方法   或者 用   上/下一个排列 . 

 1 //  这是一种很常用的方法   ,平时的搜索  都是这 一种形式
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<math.h>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #include<stack>
12 using namespace std;
13 int tot,c[1000],vis[3][1000],n,a[11];
14 void search(int cur)
15 {
16     if(cur==n)
17         tot++;
18     else
19         for(int i=0;i<n;i++)
20     {
21         if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])
22         {
23             c[cur]=i;
24             vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
25             search(cur+1);
26             vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
27         }
28     }
29 }
30 int main()
31 {
32     for(n=1;n<=10;n++)
33     {
34         tot=0;
35         memset(c,0,sizeof(c));
36         memset(vis,0,sizeof(vis));
37         search(0);
38         a[n]=tot;
39     }
40     while(scanf("%d",&n),n)
41     {
42         printf("%d\n",a[n]);
43     }
44     return 0;
45 }

 下面附上另一个用时最短0ms  并且 容易理解的   

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<stack>
11 using namespace std;
12 int n,c[10],tot,a[11];
13 void search(int cur)
14 {
15     if(cur==n)  //递归边界 , 只要走到了这里 , 所有皇后必然不冲突 .
16         tot++;
17     else
18         for(int i=0;i<n;i++)
19     {
20         int ok=1;
21         c[cur]=i;       // 尝试将  cur 行的  皇后放在  i 列 .
22         for(int j=0;j<cur;j++)   //  检查是否 个 前面的皇后冲突
23         {
24             if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])   //
25             {
26                 ok=0;
27                 break;
28             }
29         }
30         if(ok)
31             search(cur+1);
32     }
33 }
34 int main()
35 {
36     for(n=1;n<=10;n++)
37     {
38         memset(c,0,sizeof(c));
39         tot=0;
40         search(0);
41         a[n]=tot;
42     }
43     while(scanf("%d",&n),n)                //   几皇后 ?
44     {
45         printf("%d\n",a[n]);
46     }
47 }

 

posted @ 2016-03-24 15:40  X-POWER  阅读(583)  评论(0编辑  收藏  举报