• N皇后问题 回溯非递归算法 C++实现2


    运行结果

    代码如下

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int MAX = 1024;
     4 const char *LINE32 = "--------------------------------";
     5 const bool PRINT_DETAILS = false; 
     6 long long n, cnt = 0;// n表示皇后数量,cnt表示方案数量
     7 int vis[3][2*MAX+1];
     8 //v[0][]、v[1][]、v[2][]分别表示列、主对角线、副对角线是否存在皇后
     9 // 为0时表示无皇后,非0则表示有,且v[0][4]=2表示第四列第二行存在皇后 
    10 
    11 void print() {
    12     cout << LINE32 << endl;
    13     cout << "" << cnt << "个方案: " << endl;
    14     for (int i = 1; i <= n; i++) {
    15         if (i != 1) {
    16             cout << ", ";
    17         }
    18         cout << "(" << vis[0][i] << "," << i << ")";
    19     } 
    20     cout << endl;
    21     for (int i = 1; i <= n; i++) {
    22         for (int j = 1; j <= n; j++) {
    23             if (vis[0][j] != i) {
    24                 cout << 'x';
    25             } else {
    26                 cout << 'Q';
    27             }
    28         }
    29         cout << endl;
    30     }
    31 }
    32 
    33 bool check(int row, int col) {// 检查是否可以在(row,col)这个坐标放置皇后
    34     return !(vis[0][col] || vis[1][row-col+n] || vis[2][row+col]);
    35 }
    36 void place(int x, int y, int *r2c) {// 在(x,y)的位置上放置皇后 
    37     vis[0][y] = x;
    38     vis[1][x-y+n] = vis[2][x+y] = 1;
    39     r2c[x] = y;
    40 } 
    41 void remove(int x, int y) {// 移除(x,y)位置上的皇后 
    42     vis[0][y] = vis[1][x-y+n] = vis[2][x+y] = 0;
    43 } 
    44 void solve(int n) {// 与非递归实现1的不同点在于,A.使用了vis[3][]加快了判断,B.回溯的具体操作是在vis[3][]上而不是r2c[]上 
    45     int r2c[n+5];// 存放各行所放位置的列数,其实类似于递归实现1和非递归实现1中使用的queen[] 
    46     r2c[0] = 0;// 这里要初始化,否则最后要退出下面的循环时会数组越界,受影响的代码是63_42 
    47     int row = 1, col = 1;
    48     place(row, col, r2c);
    49     row = 2;//在(1,1)的位置上放置一个皇后,然后进入循环,开始寻找第二行放置的位置
    50     while (row > 0) {// row的值最后为0,因为所有情况都检查完时,第一行往上回溯,row值就为0
    51         if (row > n) {
    52             // 找到一个解,之后需要向上回溯:移除上一行的皇后,从上一行的下一列尝试放置皇后 
    53             cnt++;
    54             if (PRINT_DETAILS) {
    55                 print();
    56             } 
    57             row--;// row返回上一行
    58             remove(row, r2c[row]);// 移除上一行中的皇后
    59             col = r2c[row]+1;// 此时的(row,col)为下一次尝试放置的位置 
    60         } else if (col > n) {
    61             // 当前row行中的每一个位置都尝试并放置了,回溯
    62             row--;
    63             remove(row, r2c[row]);
    64             col = r2c[row]+1; 
    65         } else if (check(row, col)) {
    66             // 找到一个符合的位置
    67             place(row, col, r2c);// 放置皇后 
    68             row++;// 查找下一行放置的位置
    69             col = 1;// 并且是从第一列开始放置 
    70         } else {
    71             // 这一列不符合,查找下一列 
    72             col++; 
    73         } 
    74     } 
    75 }
    76 
    77 int main() {
    78     // input
    79     cout << "输入皇后个数: "; 
    80     cin >> n;
    81     // compute
    82     clock_t begin = clock(); 
    83     solve(n); 
    84     clock_t end = clock(); 
    85     // output
    86     cout << LINE32 << endl;
    87     cout << n << "皇后问题一共有" << cnt << "种解决方案" << endl; 
    88     cout << LINE32 << endl;
    89     cout << "回溯非递归算法实现2 解决" << n << "皇后问题耗时" << /*end-begin << "打点" <<*/(double)(end-begin)/CLOCKS_PER_SEC  << "s" << endl;
    90     return 0;
    91 }
    92 // 14 3~5s

    与回溯递归算法实现2对比

    回溯递归算法实现2运行情况

    回溯非递归算法实现2运行情况

    非递归实现还是比递归实现慢一点,有点不符合预期。

  • 相关阅读:
    虚方法表与动态分派机制
    方法重载与invokevirtual字节码指令的关系
    栈桢与操作数栈以及符号引用与直接引用的转换
    通过字节码分析this关键字以及异常表的作用
    JVM synchronized关键字所生成的字节码
    window Chrome 下允许跨域访问服务端接口设置
    JVM Java字节码方法表与属性
    JVM 字节码的结构
    Jar hell问题以及解放方法
    JVM 线程上下文类加载器
  • 原文地址:https://www.cnblogs.com/realize1536799/p/12731561.html
Copyright © 2020-2023  润新知