4 条题解

  • 7
    @ 2022-12-27 15:08:27

    做这道题,我们要解决如下问题:

    • 如何判断是否在 k 列 i 行可行?
    • 放下一个皇后后,怎么让其所在行,列,两条斜线都不能再次放置另一个皇后?
    • 如果某一列的每一行都无法再次放置皇后,要怎么回溯到上一次?
    • 如果k==8时,输出一个可行解后怎么在查找下一个可行解?
    • -最后我们要怎么退出?

    A. 对于①、②问题,我们先要找到一种方式来储存可行解,当然我们也可以用二维数组来模拟棋盘,每放置一个皇后就把这位置标记下来,并把所在行列斜线都标记为false,再进行下一次放置皇后时,根据该行该列是否是 false 来放置。但自习思考这样会造成标记和输出上的麻烦 。为了使问题便于思考和简化代码,我们可以采取以下方法。

    • 用一维数组 col[9] 来表示每列上皇放置的位置,如row[A]=B:代表第 A 列第9行放置了一个皇后。
    • 用 bool row[9],digLeft[16],digRight [16]分别表示每行,左低右高线和右低左高线上是否被禁止放置皇后。如row[A]=false,digLeft[B]=false,digRight[C]=false,表示第 A 行,第B条左低斜线和第C条右高斜线上不能放置皇后。至于列就不用了管它了。通过规律我们可以把 B 和 C 用 k 和 i 表示出来。

    B. 对于③,但循环 i=9 时自然会退出回溯到上一次放置皇后,不过我们要额外加一条代码来取消上一次的标记。对于④也是同理。

    C. 当我们把所有能够试探的方法试探玩后,k=9,自然就会退出递归。

    一切都思考清楚后就可以释放代码了,奥利给!

    AC代码

    #include <iostream>
    using namespace std;
    void queen_all(int k,int n);
    int col[100]={0},times=0;     //用times来记录一共多少种结果
    bool row[100]={0},digLeft[100]={0},digRight[100]={0};
    int main()
    {
        int n=0;
        cin>>n;
        queen_all(1,n);
        cout<<times;
        return 0;
    }
    void queen_all(int k,int n)
    {
        int i=0;
        for (i=1;i<=n;++i)
        {
            if (row[i]!=1&&digLeft[k+i-1]!=1&&digRight[n+k-i]!=1)
            {
                col[k]=i;
                row[i]=digLeft[k+i-1]=digRight[n+k-i]=1;
                if (k==n)
                {
                    for (int j=1;j<=n;++j)
                        cout<<col[j]<<' ';
                    cout<<endl;
                    ++times;
                }
                else queen_all(k+1,n);
                row[i]=digLeft[k+i-1]=digRight[n+k-i]=0;
            }
        }
    }
    
    • 0
      @ 2023-6-5 22:55:21

      xyz表示竖列和两个斜列,话说为什么数据范围6~10会有10个样例啊(

      #include<bits/stdc++.h>
      using namespace std;
      bool x[20],y[50],z[50];
      int n,a[17],ans;
      void dfs(int d)
      {
          if (d==n+1)
          {
              for (int i=1;i<=n;i++)
                  cout<<a[i]<<" ";
              cout<<'\n';
              ans++;
              return;
          }
          for (int i=1;i<=n;i++)
              if (!x[i]&&!y[i+d]&&!z[i-d+n])
              {
                  x[i]=1,y[i+d]=1,z[i-d+n]=1;
                  a[d]=i;
                  dfs(d+1);
                  x[i]=0,y[i+d]=0,z[i-d+n]=0;
              }
      }
      int main()
      {
          cin>>n;
          dfs(1);
          cout<<ans;
          return 0;
      }
      • -1
        @ 2022-10-26 21:24:54
        #include<bits/stdc++.h>
        using namespace std;
        // total表示方案数,a[i]表示第i行摆放了棋子的位置
        // b[i]、c[i]、d[i]表示当前列、对角线上摆放了棋子的位置
        int n,total,a[25],b[25],c[25],d[25];
        void dfs(int i){
            if(i>n){ // i>n说明搜索到了第n+1行,此时已经找到一个方案
                for(int j=1;j<=n;j++)
                    cout<<a[j]<<" ";
                cout<<"\n";
                total++;
                return;
            }
            for(int j=1;j<=n;j++)
                if(a[i]==0&&b[j]==0&&c[i+j]==0&&d[i-j+n]==0){ // 满足不重复时
                    a[i]=b[j]=c[i+j]=d[i-j+n]=j; // 记录当前位置
                    dfs(i+1); // 递归调用搜索下一行
                    a[i]=b[j]=c[i+j]=d[i-j+n]=0; // 回溯
                }
        }
        int main(){
            ios::sync_with_stdio(false); // 输入输出加速
            cin.tie(0);
            cout.tie(0);
            cin>>n;
            dfs(1); // 由第1行开始搜索
            cout<<total;
            return 0;
        }
        
        • -1
          @ 2022-7-20 9:55:08
          #include <bits/stdc++.h>
          using namespace std;
          int n, ans, a[100];
          bool vis1[100], vis2[100], vis3[100];
          void dfs(int step) {
          if (step == n + 1) {
          ans++;
          for (int i = 1; i <= n; i++) {
          cout << a[i] << " ";
          }
          cout << endl;
          return;
          }
          for (int i = 1; i <= n; i++) {
          if (!vis1[i] && !vis2[i - step + 15] && !vis3[i + step]) {
          vis1[i] = 1, vis2[i - step + 15] = 1, vis3[i + step] = 1;
          a[step] = i;
          dfs(step + 1);
          vis1[i] = 0, vis2[i - step + 15] = 0, vis3[i + step] = 0;
          }
          }
          }
          int main() {
          cin >> n;
          dfs(1);
          cout << ans;
          return 0;
          }
          
          • @ 2022-9-4 8:57:07

            最好别用万能头

        • 1

        信息

        ID
        1912
        时间
        1000ms
        内存
        256MiB
        难度
        3
        标签
        递交数
        174
        已通过
        95
        上传者