zoukankan      html  css  js  c++  java
  • Leetcode | N-Queens I & II

    N-Queens I

    The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

    Given an integer n, return all distinct solutions to the n-queens puzzle.

    Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

    For example,
    There exist two distinct solutions to the 4-queens puzzle:

    [
     [".Q..",  // Solution 1
      "...Q",
      "Q...",
      "..Q."],
    
     ["..Q.",  // Solution 2
      "Q...",
      "...Q",
      ".Q.."]
    ]

    Wiki:任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

    回溯,用了一个数组col[i]来表示第i列是不是已经放了queen。

    对于(row1, col1)和(row2, col2)这两个位置,如果它们在同一对角线上,那么有abs(row1-row2) = abs(col1-col2)。

    class Solution {
    public:
        vector<vector<string> > solveNQueens(int n) {
            if (n == 2 || n == 3) {
                return ret;
            }
            vector<string> sol(n, string(n, '.'));
            vector<bool> col(n, false);
            bt(n, 0, col, sol);
            return ret;
        }
        
        void bt(int n, int r, vector<bool> &col, vector<string> &sol) {
            if (r >= n) {
                ret.push_back(sol);
                return;
            }
        
            for (int i = 0; i < n; ++i) {
                if (col[i]) continue;
    
                bool diag = false;
                for (int j = r - 1; j >= 0; --j) {
                    for (int m = 0; m < n; ++m) {
                        if (abs(j - r) == abs(m - i) && sol[j][m] == 'Q') {
                            diag = true;
                            break;
                        }
                    }
                }   
                
                if (!diag) {
                    col[i] = true;
                    sol[r][i] = 'Q';
                    bt(n, r + 1, col, sol);
                    col[i] = false;
                    sol[r][i] = '.';
                }
            }
            
        }
    
    private:
        vector<vector<string> >  ret;
    };

     N-Queens II

    Follow up for N-Queens problem.

    Now, instead outputting board configurations, return the total number of distinct solutions.

    和N-Queens I 类似,同样需要回溯。

    前面回溯的时候需要用到一个额外的数组col[i],而且用到了sol这个数组来判断对角线元素。

    网上的解决方案更巧妙些,用到一个数组sol[i],存的是第i行可解的列号。

    当处理到第r行时,检查前r-1行,看sol[0...r-1]有没有等于i的,有就代表了该列已经有queen了。然后再检查对角线上的。

     1 class Solution {
     2 public:
     3     int totalNQueens(int n) {
     4         if (n == 2 || n == 3) {
     5             return 0;
     6         }
     7         vector<int> sol(n, -1);
     8         total = 0;
     9         bt(n, 0, sol);
    10         return total;
    11     }
    12     
    13     void bt(int n, int r, vector<int> &sol) {
    14         if (r >= n) {
    15             total++;
    16             return;
    17         }
    18     
    19         for (int i = 0; i < n; ++i) {
    20             bool valid = true;
    21             for (int j = r - 1; j >= 0; --j) {
    22                 for (int m = 0; m < n; ++m) {
    23                     if (sol[j] == i || abs(j - r) == abs(sol[j] - i)) {
    24                         valid = false;
    25                         break;
    26                     }
    27                 }
    28             }   
    29             
    30             if (valid) {
    31                 int t = sol[r];
    32                 sol[r] = i;
    33                 bt(n, r + 1, sol);
    34                 sol[r] = t;
    35             }
    36         }
    37         
    38     }
    39 
    40 private:
    41     int total;
    42 };

     第三次写,在返回值统计。至此leetcode三遍刷完。

     1 class Solution {
     2 public:
     3     int totalNQueens(int n) {
     4         if (n <= 0) return 0;
     5         vector<int> colSetted(n, -1);
     6         return recurse(n, 0, colSetted);
     7     }
     8     
     9     int recurse(int n, int row, vector<int> &colSetted) {
    10         if (row >= n) {
    11             return 1;
    12         }
    13         
    14         int count = 0;
    15         for (int i = 0; i < n; ++i) {
    16             if (colSetted[i] == -1) {
    17                 bool couldSet = true;
    18                 for (int j = 0; j < n; ++j) {
    19                     if (colSetted[j] != -1 && abs(row - colSetted[j]) == abs(i - j)) {
    20                         couldSet = false;
    21                         break;
    22                     }
    23                 }
    24                 if (couldSet) {
    25                     colSetted[i] = row;
    26                     count += recurse(n, row + 1, colSetted);
    27                     colSetted[i] = -1;
    28                 }
    29             }
    30         }
    31         return count;
    32     }
    33 };
  • 相关阅读:
    一些话
    把视频文件拆成图片保存在沙盒中
    相册视频保存进沙盒
    数据库
    C 计算数组长度
    iOS之与JS交互通信
    iOS之duplicate symbols for architecture x86_64错误
    iOS之隐藏状态栏
    iOS之开发程序之间的跳转及跳转到appStore
    iOS之常用的判NULL的方法
  • 原文地址:https://www.cnblogs.com/linyx/p/3718873.html
Copyright © 2011-2022 走看看