描述:
位運算是定義在整數上的運算。但在做位運算的時候,並不把整數看作整數,而是將它們看做一系列二進位制數字,逐位進行運算。位運算有6種,他們的名稱,運算子及運算規則如下:
與 (and): 5 & 6 = 4 (101 & 110 = 100)
或 (or): 5 | 6 = 7 (101 | 110 = 111)
異或 (xor): 5 ^ 6 = 3 (101 ^ 110 = 011)
取反 (not / complement): ~5 = -6 (~00000101 = 11111010)
左移 (shift left): 5 << 2 = 20 (101 << 2 = 10100)
右移 (shift right): 5 >> 2 = 1 (101 >> 2 = 1)
說明:操作:
設 a 為乙個bit array 陣列
問題的輸入:
輸入為乙個自然數 n ,表示棋盤的大小。
樣例:6
問題的輸出:
輸出為前三個按照字典序排列的解,最後一行為解的總數。
樣例:2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4**:
#include
using
namespace std;
int n , ans[
1000];
long lime =
1, total =0;
//total為解的總數,lime的目的為生成n個由1組成的二進位制數字。
inttrans
(long num)
return flag;
}void
test
(long a,
long b,
long c,
int row)
}else
cout<
} total++;}
}int
main()
每一行只能放並且必須放乙個棋子。每次放置乙個棋子之後,它就會對後面所有行中,可能放置棋子的位置產生影響。以下圖為例,我們已經放置了三個棋子q1,q2,q3。 接著在下面一行放置q4時,用彩色標註出的區域都是不可行的方案,會與已經放置的三個棋子產生衝突。
這個衝突其實有三種不同的情況,我們用三個變數a,b,c分別來表示這三種不同的衝突。這三個變數都是乙個八位的二進位制數,這八位中,為1的表示有衝突,為0表示沒有衝突。這三種衝突分別為:
與已放置的棋子處於同一列中;
我們用a表示這種衝突。例如在圖中,第四行會有三個位置因為列攻擊而不能再放置棋子(圖中大紅色方塊),因此a = 1000 1001。
與已放置的棋子處於同一左斜對角線中;
用b表示這種衝突。例如在圖中,藍色方塊所表示的位置,分別是由於q1和q2的左斜對角線上的攻擊而不能夠放置新的棋子, 因此b= 0001 0010。
與已放置的棋子處於同一右斜(指向右上方)對角線中。
用c表示這種衝突。例如圖中粉色方塊, 是由q2的右斜對角線的攻擊造成的,因此c = 0010 0000。
有了a,b,c,三個變數,我們很容易求出當前這一行中,有哪些位置是可以放置棋子的。這個變數我們用d來表示,我們可以寫出d = ~(a|b|c)。d中為1的那些位置則是我們可以放置棋子的位置。在上圖的情況下d = 0100 0100。此時,有兩個可能的放置棋子的位置,用bit表示可能的乙個位置,使用bit =d & (-d)可取出d中最右邊的乙個1。 在下乙個遞迴函式中傳入的引數:
1.對於豎直方向上產生的衝突: a |= bit 。在a中將bit為 1的一位變成1,表示這一列已經放過棋子了。
long lime = 1;
lime = (lime << n ) -1; 生成n個由1組成的二進位制數字。
摘抄,侵刪
end.
演算法 位運算 與 n皇后問題
問題a 返回n皇后擺法有多少種?遞迴函式,維護三個變數和乙個常量 常量 upperlim 代表棋盤大小,末尾n個1,例如八皇后,00 011111111 變數 顯然,遞迴函式的跳出條件為,nowlim upperlim 其中每層遞迴函式,可以通過位運算快速找到可以擺放的位置。pos upperlim...
位運算的魅力 N皇后問題
有乙個n n的棋盤,有些格仔可以放置皇后,乙個皇后可以對它這一行的位置,這一列的位置,它所在的左對角線和右對角線攻擊,這些位置不能放置皇后,一共放置n個皇后,問有多少種放置的方式。輸入格式 第一行有乙個n。接下來有n行n列描述乙個棋盤,表示可放 表示不可放。輸出格式 輸出方案總數 這道題主要考察位運...
n皇后 位運算版
n皇后問題是大家在遞迴裡會碰到的乙個經典問題。以前高中我學dfs的時候,老師首先讓我看的就是八皇后。不過這皇后的時間複雜度大家可想而知了。而接下來的位運算將這個效率重新提到乙個高度。我是以前在matrix67大牛那裡學的,最近資料結構實驗剛好碰到n皇后,就在這裡 複述 一遍吧。code void d...