最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

八皇后問題的位運算解決

2022-10-22 05:33 作者:-王-小-明-  | 我要投稿

如題:

一道很經(jīng)典的八皇后問題

這是最后的代碼:

這八層循環(huán)有一種放蕩不羈的美

開始我是想用遞歸做的,畢竟這本來就是遞歸練習(xí)題。

可遞歸太難,不想用,又寫不出來。在我走投無路之際,我突然想到了位運算。

8這個數(shù)字本身就很好玩,正好是一個字節(jié)的位數(shù),也是C語言支持的最小長度的int類型的長度。

于是我的思路開始清晰:如果這八行都各用一個%5C_%5C_int8表示,總共是一個8長的%5C_%5C_int8數(shù)組,不就可以表示出棋盤上皇后的位置了嗎?(但這里的%5C_%5C_int8埋下了伏筆)

這樣一來,每行都可以從1開始,每次向左移1位,這樣每行都只會有一個皇后。但需要寫八層循環(huán)。當然,我們也可以用遞歸的方法來寫,如果以后我有時間會改一下,畢竟八層循環(huán)確實很丑。

而在從第二層開始的每層循環(huán)開始前,我們都可以先檢查一下這個落子位置是否會和前面的皇后在同一列。而一個一個比較不如把前面的存起來,這就又需要一個temp數(shù)組。

每次放下皇后,也把這個皇后放進該層的temp里,下層的temp又繼承上層的temp,并再加一個該層的皇后。這樣,接下來的循環(huán)中,如果這個數(shù)和上次的temp進行按位與操作之后不為0,那就說明不能放在這里,可以continue%3B了。

這樣一來,當我們走到循環(huán)底部時,就可以獲得一個每行、每列都有且僅有一個皇后的狀態(tài)??蛇@還不算完,因為皇后還可以斜著吃。那又該怎么辦?

我的思路到這里突然卡了一下,但我瞬間卻又想到了解決方案:移位+按位與!

我們從第一行開始遍歷。顯然,第i行應(yīng)該滿足如下條件:

(lines%5Bi%5D%20%3C%3C%20j)%20~%5C%26%20~%20lines%5Bi%20%2B%20j%5D%20%3D%200%2C(lines%5Bi%5D%20%3E%3E%20j)%20~%5C%26%20~%20lines%5Bi%20%2B%20j%5D%20%3D%200%2Cj%3E0%2Ci%2Bj%3C8

寫到這里的時候,我突然有了新想法:在八層循環(huán)的時候,我們是不是已經(jīng)可以這樣去操作了呢?我們可以再開一個temp2數(shù)組。

temp2數(shù)組的第i個元素是(lines%5B0%5D%20%3C%3C%20i)~%7C~(lines%5B0%5D%20%3E%3E%20i)~%7C~(lines%5B1%5D%3C%3C(i-1))~%7C~(lines%5B1%5D%3E%3E(i-1))~%7C~...~%7C~(lines%5Bi-1%5D%3C%3C1)%7C(lines%5Bi-1%5D%3E%3E1)

但這次的數(shù)組并沒有上下繼承關(guān)系,因此每次都是重新計算。

這樣,當我們在遍歷lines%5Bi%5D的時候,只需要判斷lines%5Bi%5D~%5C%26~temp2%5Bi-1%5D,若不為0,那么我們已經(jīng)可以給它判死刑,執(zhí)行continue%3B。

無論如何,我們終于得到了想要的:一個符合標準的八皇后棋盤。接下來就是輸出的問題了。

按照我們的思路,皇后是一行一行地遍歷,而遍歷順序是從右往左。題目要求的輸出則是按列遍歷,從上到下。那該怎么辦呢?

其實換個視角,問題就得到解決了。我們可以把這八個數(shù)字豎著放,并且倒著讀。這樣就是按列從上到下了。數(shù)字放好,仍然一行一行輸出,問題就完美解決了。

豎著放很簡單,倒著讀?怎么讀?

我們先看怎么讀。這個問題其實蠻簡單的,同樣是按位與,同樣是循環(huán)移位。我們判斷lines%5Bi%5D~%5C%26~(2%20%3C%3Cj),當其非零時,得到的j就是我們要的坐標。等等,這樣不就實現(xiàn)倒著讀了嗎?

哈哈,的確是這樣。我們之前從右到左的反常遍歷順序就是移位帶來的,現(xiàn)在我們?nèi)匀挥靡莆缓桶次慌c來讀取,自然就“負負得正”了。

自然,我們也可以從0xF0開始向右移位,這樣就是從左到右的遍歷,更符合我們的思維習(xí)慣,不是嗎?

到這里,算法設(shè)計基本告一段落,接下來便是debug時間——我的程序怎么不輸出?

我首先發(fā)現(xiàn)的是運算符優(yōu)先級的隱患。于是我多加了一些括號:這總是有益無害的。然而剛剛我去查證,那些括號實際上并沒有起到什么作用。

上文我寫到,%5C_%5C_int8埋下了伏筆,這是因為%5C_%5C_int8實際上是有符號數(shù)。有符號數(shù)!這意味原本的0xF0在這里并不表現(xiàn)為128,而是-128.

這導(dǎo)致它在移位的時候會出現(xiàn)各種奇奇怪怪的數(shù)字——這是在我調(diào)試的時候發(fā)現(xiàn)的。我一開始并沒有意識到這是有符號數(shù)導(dǎo)致的。于是我查了很久%5C_%5C_int8的移位機制。

但我還是不理解。于是我想用%5C_%5C_int16,但考慮之后發(fā)現(xiàn)這是不可行的。因為越界的移位會被保留,而這可能導(dǎo)致本來按位與是0的兩個數(shù)按位與后非0.

8這個數(shù)本身就很整,為什么要加一倍呢?

對啊,8本身就很整,為什么不行呢?

然后,我突然意識到了。之所以會出現(xiàn)負號,就是因為用了有符號數(shù)!

我迅速把%5C_%5C_int8改成了%5C_%5C_UINT8%5C_TYPE%5C_%5C_,運行,輸出了!AC!

我抑制住激動的心情,敲下了這篇專欄。

當然,這里還有一個小問題沒有提到,那就是多層循環(huán)的跳出問題,在判斷是否在同一斜線上時,這里有一個兩層循環(huán)的break%3B%2B一層循環(huán)的continue%3B,判斷循環(huán)變量不是一個明智的選擇,因為這需要將它的定義置于循環(huán)體外。因此,加一個是否仍符合條件的判斷標志以幫助跳出多層循環(huán)是更為方便而安全的選擇。

當然,一定不要用goto語句。

另外一個是oj題特有的輸出問題,雖然我們已經(jīng)見過很多次,并且這并非一個大問題,但我仍要提一句。它不允許輸出行的最后有多余的空格,并且這個空格并不能用'%5Cverb%7C%5C%7C%20b'來刪除。

我們的解決辦法一般是這樣的:將第一個輸出單獨拿出來,不打空格;從第二個開始,每個輸出都是一個空格+所需輸出。

現(xiàn)在是凌晨4:52,這篇專欄寫了大概2h,是時候收工睡覺了。

八皇后問題的位運算解決的評論 (共 條)

分享到微博請遵守國家法律
虎林市| 漯河市| 郯城县| 华安县| 宜兴市| 徐水县| 德钦县| 广水市| 武乡县| 民丰县| 无极县| 兴山县| 南乐县| 吉木乃县| 盐山县| 威远县| 丽江市| 洪洞县| 宁晋县| 北宁市| 璧山县| 咸宁市| 黔西| 赤城县| 凤凰县| 泰州市| 萨嘎县| 兰考县| 东明县| 隆回县| 慈溪市| 汽车| 静安区| 安平县| 海原县| 辽源市| 交口县| 连平县| 杭锦后旗| 寿宁县| 抚顺市|