• 深度优先搜索 之 CODE[VS] 1295 N皇后问题


    /*
    dfs,关键:检查皇后会发生攻击的状态。
    两种方法:(第二种,速度更快)
    	(1)void Solve(int row, int colUsed);
    		常规办法,判断状态是否非法的方法:列上通过位运算;左斜、右斜通过遍历。
    	(2)void SolveBitOperation(unsigned col, unsigned tiltLeft, unsigned tiltRight);
    		完全位运算,具体参考代码注释。
    		另外可参考Matrix67的博客(有图,很形象):http://www.matrix67.com/blog/archives/266
    		C++实现参考:http://www.cnblogs.com/lee41sum/archive/2010/04/22/1717986.html
    		
    */
      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <cstddef>
      5 #include <iterator>
      6 #include <algorithm>
      7 #include <string>
      8 #include <locale>
      9 #include <cmath>
     10 #include <vector>
     11 #include <cstring>
     12 #include <map>
     13 #include <utility>
     14 #include <queue>
     15 #include <stack>
     16 #include <set>
     17 using namespace std;
     18 const int INF = -0x3f3f3f3f;
     19 const int MaxN = 55;
     20 const int modPrime = 3046721;
     21 
     22 int n;
     23 bool isUsedNode[20][20];
     24 int answer = 0;
     25 
     26 //----------------------------------方法一----------------------------------
     27 bool isAttack(int row, int col, int colUsed)
     28 {
     29     if (colUsed&(1 << col))
     30     {
     31         return true;
     32     }
     33     for (int i = row - 1, j = col - 1, k = col + 1; i > 0; --i, --j, ++k)
     34     {
     35         if (j > 0)
     36         {
     37             if (isUsedNode[i][j])
     38             {
     39                 return true;
     40             }
     41         }
     42         if (k <= n)
     43         {
     44             if (isUsedNode[i][k])
     45             {
     46                 return true;
     47             }
     48         }
     49     }
     50     return false;
     51 }
     52 
     53 void Solve(int row, int colUsed)
     54 {
     55     if (row == n+1)
     56     {
     57         ++answer;
     58         return;
     59     }
     60     for (int col = 1; col <= n; ++col)
     61     {
     62         if (!isAttack(row, col, colUsed))
     63         {
     64             isUsedNode[row][col] = true;
     65             Solve(row + 1, colUsed | (1 << col));
     66             isUsedNode[row][col] = false;
     67         }
     68     }
     69 }
     70 
     71 //----------------------------------方法而----------------------------------
     72 unsigned limN; // N个皇后目标状态(所有列都已有皇后,注:这里的列是指将N行压缩成一行,一共有N列)
     73 void SolveBitOperation(unsigned col, unsigned tiltLeft, unsigned tiltRight)
     74 {                    //  列非法位置       左斜产生的非法位置         右斜产生的非法位置
     75     if (col == limN)
     76     {
     77         // 所有列都已有皇后
     78         ++answer;
     79         return;
     80     }
     81     unsigned freePosSet = limN&(~(col | tiltLeft | tiltRight)); // 获得不会发生冲突的列集合
     82     while (freePosSet)
     83     {
     84         unsigned freePos = freePosSet&((~freePosSet) + 1); 
     85         // 在不会发生冲突的列集合中,获取最右边的列位置(如果直接想不出来这条语句的原因,举个例子自己推演一下)
     86         /*
     87             eg: 
     88                       freePosSet 二进制:01010010
     89                      ~freePosSet 二进制:10101101
     90                  (~freePosSet)+1 二进制:10101110
     91   freePosSet&((~freePosSet) + 1) 二进制:00000010
     92 
     93         */
     94         freePosSet -= freePos;
     95         // 在没有冲突的列集合中,去掉当前行已用过的列位置
     96         SolveBitOperation(col | freePos, (tiltLeft | freePos) << 1, (tiltRight | freePos) >> 1);
     97             //到了下一行: 增加一个非法列位置(即当前行皇后所占的列位置)  
     98             //            因为当前行多了一个皇后,所以左斜到下一行多了一个非法位置,右斜到下一行多了一个非法位置
     99     }
    100 }
    101 
    102 int main()
    103 {
    104 #ifdef HOME
    105     freopen("in", "r", stdin);
    106     //freopen("out", "w", stdout);
    107 #endif
    108 
    109     memset(isUsedNode, false, sizeof(isUsedNode));
    110     cin >> n;
    111     // 方法一
    112     //Solve(1, 0);
    113     // 方法二
    114     limN = (1 << n) - 1;
    115     SolveBitOperation(0, 0, 0);
    116     cout << answer << endl;
    117 
    118 #ifdef HOME
    119     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
    120     _CrtDumpMemoryLeaks();
    121 #endif
    122     return 0;
    123 }
    
    
    

  • 相关阅读:
    JSTL基础知识
    EL表达式基础知识
    Log4Net使用详解
    ViewState存储到服务器
    WCF通信过程
    值类型与引用类型总结
    使用 HttpWebRequest 发送模拟 POST 请求
    OOP组合和继续的优缺点
    XPath在asp.net中查询XML
    Equal 和==比较
  • 原文地址:https://www.cnblogs.com/shijianming/p/5020209.html
Copyright © 2020-2023  润新知