zoukankan      html  css  js  c++  java
  • hdu1116回溯N皇后问题

    题目连接

    经过思考,不难发现:恰好N个皇后放在不同行不同列,那么是不是可以转换成N个皇后所在行分别确定(一人一行)的情况下对她们的所在列的枚举。

    也就是列的全排列生成问题,我们用c[x]表示x行皇后的列编号。而我们知道0~N-1的排列一共有N的阶乘,枚举量不会超过它。

    if(cur==n)//递归边界。只要走到这里,所有的皇后必然不冲突
        tot++;

    根据我们的代码,我们是从cur=0开始的,

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,tot,c[1000];
     5 void search(int cur)
     6 {
     7     int i,j;
     8     if(cur==n)//递归边界。只要走到这里,所有的皇后必然不冲突
     9     tot++;
    10     else
    11     for(i=0;i<n;i++)
    12     {
    13         int ok=1;
    14         c[cur]=i;//尝试把第cur行的皇后放在第i列
    15         for(j=0;j<cur;j++)
    16         if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])//检查是否与前面的皇后冲突
    17         {
    18             ok=0;break;
    19         }
    20         if(ok)
    21         search(cur+1);//如果合法,继续递归
    22     }
    23 }
    24 int main()
    25 {
    26     int a[15];
    27     for(int i=0;i<10;i++){
    28         tot=0;
    29         n=i+1;
    30         search(0);
    31         a[n]=tot;
    32     }
    33     while(cin>>n&&n)
    34     {
    35         cout<<a[n]<<endl;
    36     }
    37 }

    search(cur+1);//如果合法,继续递归       并不会判断n+1行的皇后。所以我们从cur=0开始。

    当然从cur=1开始也是可以的,但此时

     if(cur==n+1)//递归边界。只要走到这里,所有的皇后必然不冲突

    tot++;

    程序中的

    if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])//检查是否与前面的皇后冲突
            {
                ok=0;break;
            }

    既然是逐行放置,那么皇后肯定不会横向攻击,因此只需检查是否纵向和斜向攻击即可。条件c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])

     y-x标示了主对角线,斜率为1;

     y+x标示了副对角线,斜率为-1;

    画画图就知道了

    我们还可以用二维数组vis[2][]直接判断当前尝试放的皇后的对角线和纵向有没有皇后已经放了,注意主对角线标示y-x可能为负数,所以要加n

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 int n,tot,c[1000];
     7 int vis[3][1000];
     8 void search(int cur)
     9 {
    10     if(cur==n)tot++;
    11     else{
    12         for(int i=0;i<n;i++){
    13             if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){
    14             c[cur]=i;//如果不需要打印皇后所在列,可以舍去
    15             vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;//标示这些空已经不能再放皇后
    16             search(cur+1);
    17             vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;//回溯要改回来
    18             }
    19         }
    20     }
    21 }
    22 int main()
    23 {
    24     int a[15];
    25     for(int i=0;i<10;i++){
    26         memset(vis,0,sizeof(vis));
    27         tot=0;
    28         n=i+1;
    29         search(0);
    30         a[n]=tot;
    31     }
    32     while(cin>>n&&n)
    33     {
    34         cout<<a[n]<<endl;
    35     }
    36 }
  • 相关阅读:
    BZOJ 1072: [SCOI2007]排列perm
    BZOJ 1071: [SCOI2007]组队
    HDP集群部署
    使用Kubeadm部署kubernetes集群
    Docker 私有仓库
    Docker Compose
    Dockerfile使用
    Docker应用部署(Mysql、tomcat、Redis、redis)
    Docker 容器的数据卷 以及 数据卷容器
    Docker 服务、镜像、容器简单命令使用
  • 原文地址:https://www.cnblogs.com/WHLdbk/p/6081048.html
Copyright © 2011-2022 走看看