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


    在一个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
    ",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
    ",a[n]);
    46     }
    47 }
  • 相关阅读:
    String、StringBuffer、StringBuilder源码解读
    查询条件左边写入函数,导致无法命中索引
    【图形学手记】law of the unconscious statistician
    【图形学手记】蒙特卡洛方法相关笔记
    【图形学手记】抽样分布相关的数学笔记
    C++ lower_bound
    【图形学手记】Inverse Transform Sampling 逆转换抽样
    【Java学习笔记】LinkedList JDK1.6
    【疑难杂症】new Date() 造成的线程阻塞问题
    【疑难杂症】【Solved】maven-compiler-plugin 在 idea 下的问题
  • 原文地址:https://www.cnblogs.com/A-FM/p/5315785.html
Copyright © 2020-2023  润新知