Follow up for N-Queens problem.

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

思路1:打表
public class Solution {
public int totalNQueens(int n) {
int[] result = new int[] { 0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724,
2680, 14200, 73712, 365596, 2279184, 14772512, 95815104,
666090624 };
return result[n];
}
}

思路2:使用回溯法,參照http://blog.csdn.net/mlweixiao/article/details/40984541

public class Solution {
public static int num=0;
private boolean isValid(List<Integer> al) {
int column = al.get(al.size() - 1);
for (int i = 0; i < al.size() - 1; i++) {
if (column == al.get(i)
|| Math.abs(column - al.get(i)) == Math.abs(al.size()-1 - i)) {
return false;
}
}
return true;
} private void search(int n, List<Integer> al, int col) {
if (col > n){
num++;
}else {
for (int j = 0; j < n; j++) {
al.add(j);
if (isValid(al)) {
search(n, al, col + 1);
}
al.remove(al.size()-1);
}
}
}
public int totalNQueens(int n) {
num=0;
search(n,new LinkedList<Integer>(),1);
return num;
}
}

思路3 :回溯法。仅仅只是使用位移,速度超快,參考http://blog.csdn.net/kai_wei_zhang/article/details/8033194

如果棋盘的前i-1行已经被填充。如今我们须要填充第i行,那怎么得出第i行哪些是能够填充呢?那么有三种情况是禁止,同一列,斜率k为1的斜线,斜率k为-1的斜线。要是我们能用三个变量row。ld。rd来分别存储这三种情况的禁止位该多好啊。

以下是是六皇后问题的,如果前三行已经填充了。我们须要填充第四行


当中row。ld,rd的二进制表示如上,1代表禁止位,0代表空位(能够放皇后)。

对于第四行而言。那么第1,3。5列(从左往右数)不能放,故row的二进制表示为101010;对于第四行而言。斜率k为1的斜线有两条对其有影响,最左上的一条对第四行没有影响,k=1的中间一条斜线对第四行的影响是第一个位置(从左往右数)不能放,k=1的右下一条斜线对第四行的影响是第4个位置(从左往右数)不能放。故k=1的斜线对第四行的影响为100100(从左往右数);而k=-1的三条斜线对第四行的影响各自是第4,5,6个位置(从左往右数)不能放,故rd的二进制表示为000111(从左往右数),那么这三个数row。rd。ld二进制取‘或’就能够得到101111。101111对于第四行而言就意味着仅仅有第二个位置能放。

那么第四行填充了,这三个数row,rd。ld该怎么变化呢?row与刚填充的第二个位置(用010000表示)取或就可以。rd与刚填充的第二个位置(用010000表示)取或。还要向右移1位,由于其斜率为-1,第四行的禁止位相对于第五行而言是左上。同理,ld与刚填充的第二个位置(用010000表示)取或。还要向左移1位。当row的二进制的全部位全为1时,则表示填充完毕。


public class Solution {
// sum用来记录皇后放置成功的不同布局数。upperlim用来标记全部列都已经放置好了皇后。 static int counter = 0;
static long upperlim = 1;
// 试探算法从最右边的列開始,函数带三个參数row、ld和rd。分别表示在纵列和两个对角线方向的限制条件下这一行的哪些地方不能放
void search(long row, long ld, long rd) {
if (row != upperlim) {
// row,ld。rd进行“或”运算,求得全部能够放置皇后的列,相应位为0。
// 然后再取反后“与”上全1的数。来求得当前全部能够放置皇后的位置。相应列改为1
// 也就是求取当前哪些列能够放置皇后
long pos = upperlim & ~(row | ld | rd);
while (pos != 0) { // 0 -- 皇后没有地方可放,回溯
// 拷贝pos最右边为1的bit。其余bit置0
// 也就是取得能够放皇后的最右边的列
long p = pos & -pos;//相当于p = pos & (~pos + 1) // 将pos最右边为1的bit清零
// 也就是为获取下一次的最右可用列使用做准备,
// 程序将来会回溯到这个位置继续试探
pos -= p; // row + p,将当前列置1,表示记录这次皇后放置的列。
// (ld + p) << 1。标记当前皇后左边相邻的列不同意下一个皇后放置。 // (ld + p) >> 1,标记当前皇后右边相邻的列不同意下一个皇后放置。
// 此处的移位操作实际上是记录对角线上的限制。仅仅是由于问题都化归
// 到一行网格上来解决。所以表示为列的限制就能够了。显然。随着移位
// 在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线
// 上产生的限制都被记录下来了
search(row + p, (ld + p) << 1, (rd + p) >> 1);
}
} else {
// row的全部位都为1,即找到了一个成功的布局,回溯
counter++;
}
}
public int totalNQueens(int n) {
counter = 0;
upperlim = (1 << n) - 1;
test(0, 0, 0);
return counter;
}
}

LeetCode 51 N-Queens II的更多相关文章

  1. LeetCode Single Number I / II / III

    [1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...

  2. [array] leetcode - 40. Combination Sum II - Medium

    leetcode - 40. Combination Sum II - Medium descrition Given a collection of candidate numbers (C) an ...

  3. LeetCode 137. Single Number II(只出现一次的数字 II)

    LeetCode 137. Single Number II(只出现一次的数字 II)

  4. LeetCode:路径总和II【113】

    LeetCode:路径总和II[113] 题目描述 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树, ...

  5. LeetCode:组合总数II【40】

    LeetCode:组合总数II[40] 题目描述 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candi ...

  6. leetcode 51. N-Queens 、52. N-Queens II

    51. N-Queens 使用isValid判断当前的位置是否合法 每次遍历一行,使用queenCol记录之前行的存储位置,一方面是用于判断合法,另一方面可以根据存储结果输出最终的结果 class S ...

  7. leetcode 51. N皇后 及 52.N皇后 II

    51. N皇后 问题描述 n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回所有不同的 n 皇后 ...

  8. [Leetcode] n queens ii n皇后问题

    Follow up for N-Queens problem. Now, instead outputting board configurations, return the total numbe ...

  9. [LeetCode] 51. N-Queens N皇后问题

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

随机推荐

  1. .net缓存的应用研究(读篇)

    目前,缓存主要有两种技术:分布式缓存和进程级别的内容缓存.两种缓冲具体的差异就不废话了. 1.在技术上 数据库降压的最好方式就是缓存.在缓存的性能上,进程级别的内存缓存性能有明显优于分布式缓存,内存缓 ...

  2. sql语法中的中的with rollup

    就一道ctf题分析 http://ctf5.shiyanbar.com/web/pcat/index.php 打开一看是个登陆框,首先想到的是盲注,查看源代码,有个源文件, $filter = &qu ...

  3. oracle 10g 11g 12c区别

    oracle 10g 11g 12c区别

  4. mvc中使用Pagination,对其进行再封装

    对其进行再次封装: (function($) { $["fn"]["easyPaging"] = function(o) { if (!o.pageSelect ...

  5. CentOS下双网卡双IP不同IP段配置

    环境: eth0:10.0.7.2  gw :10.0.7.254 netmask:255.255.255.0 eth1:168.6.101.2    gw :168.6.101.254    net ...

  6. 解析 ViewTreeObserver 源码(下)

    继上篇内容,本文介绍 ViewTreeObserver 的使用,以及体会其所涉及的观察者模式,期间会附带回顾一些基础知识.最后,我们简单聊一下 Android 的消息传递,附高清示意图,轻松捋清整个传 ...

  7. 【TCP ZeroWindow】与【TCP window Full】

    1.作为接收方,有接收窗口,也就是接收缓冲区,win=xxx 告诉对方,我的接收窗口大小. 2.当我的接收窗口满了,也就是win=0,Wireshark显示[TCP ZeroWindow],这个时候, ...

  8. C#调用系统打印机和收银钱箱

    打印示例: StringBuilder builder = new StringBuilder();builder.AppendLine("--------------打印测试------- ...

  9. numpy累积

    numpy累积有两类函数:np.cumxxxxx和np.ufunc.accumulate() import numpy as np a = np.arange(1, 5) print(np.cumpr ...

  10. LVS简介与使用

    一.LVS是什么? LVS的英文全称是Linux Virtual Server,即Linux虚拟服务器.它是我们国家的章文嵩博士的一个开源项目.在linux内存2.6中,它已经成为内核的一部分,在此之 ...