深度优先搜索 之 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 }


时间: 2024-10-12 23:57:22

深度优先搜索 之 CODE[VS] 1295 N皇后问题的相关文章

深度优先搜索 之 CODE[VS] 1116 四色问题

/* dfs,需要注意输入的测试数据的格式. */ 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 &

图论 - 图的遍历 - 深度优先搜索 - n皇后问题

n皇后问题 描述 n皇后问题:一个n×n的棋盘,在棋盘上摆n个皇后,满足任意两个皇后不能在同一行.同一列或同一斜线上的方案有多少种? 输入 第一行包含一个整数n. 输出 输出一个整数,表示方案数. 样例输入 4 样例输出 2 限制 一共10个测试点, 第i个测试点的n=i+4. 时间:2 sec 空间:512 MB -------------------------------------------------------------------------------------------

深度优先搜索——八皇后问题

代码:(控制台打印不了92种情况,只打印前10种) 1 #include<iostream> 2 #include<string> 3 #include<windows.h> 4 #define ok 1 5 #define error 0 6 using namespace std; 7 8 9 int a[9][9]={0}; 10 int num=0; 11 12 int Ifblock(int x,int y) //判断有没有产生冲突 13 { 14 int i

迷宫问题 - 堆栈与深度优先搜索

堆栈的访问规则被限制为Push和Pop两种操作,Push(入栈或压栈)向栈顶添加元素,Pop(出栈或弹出)则取出当前栈顶的元素,也就是说,只能访问栈顶元素而不能访问栈中其它元素. 现在我们用堆栈解决一个有意思的问题,定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走

[Wikioi 1295]N皇后问题---两种不同的解法(复习)

题目描述 Description 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上. 输入描述 Input Description 给定棋盘的大小n (n ≤ 13) 输出描述 Output Description 输出整数表示有多少种放置方法. 样例输入 Sample Input 8 样例输出 Sample Output 92 数据范围

POJ 1979 Red and Black 深度优先搜索上手题

Red and Black Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21738   Accepted: 11656 Description There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a

sicily 1024 邻接矩阵与深度优先搜索解题

Description There are N cities and N-1 roads in Magic-Island. You can go from one city to any other. One road only connects two cities. One day, The king of magic-island want to visit the island from the capital. No road is visited twice. Do you know

1295 N皇后问题

1295 N皇后问题 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上. 输入描述 Input Description 给定棋盘的大小n (n ≤ 13) 输出描述 Output Description 输出整数表示有

[复习]深度优先搜索

深度优先搜索(dfs)是利用递归完成的以搜索深度优先的搜索 通常大概是这样的: 1 void search(int vi){ 2 if( 达到目标 ){ //边界 3 if( 不满足要求 ) return ; 4 //(和最优解比较) 5 //当比当前最优解更优时 6 //更新当前最优解 7 return ;//必须返回 8 } 9 for( int i = ...; i <= ... ; i++ ){ //枚举 10 //保存结果 11 search(vi); 12 //清除刚刚保存的结果 1