leetCode-八皇后問(wèn)題

為了使腦袋不生銹,偶爾還是需要給腦子運(yùn)動(dòng)一下爬范。今天找了一個(gè)leetCode上的一個(gè)算法來(lái)運(yùn)動(dòng)一下。
題目是這樣的:
在 8 X 8 的網(wǎng)格中弱匪,放入八個(gè)皇后(棋子)青瀑,滿(mǎn)足的條件是,任意兩個(gè)皇后(棋子)都不能處于同一行萧诫、同一列或同一斜線(xiàn)上斥难,問(wèn)有多少種擺放方式?
如果有興趣的同學(xué)可以先自己思考一下帘饶,這個(gè)題目應(yīng)該如何做哑诊。在看可能會(huì)更有體會(huì)。因?yàn)橹饕皇谴a及刻,看的還是思路 所以就沒(méi)有優(yōu)化代碼了镀裤,可能代碼比較粗糙。進(jìn)入正題:
題目描述的大概意思是缴饭,如何擺放八顆棋子是每顆棋子的上下左右 以及兩邊的正斜對(duì)角線(xiàn)上沒(méi)有棋子出現(xiàn)暑劝。用圖來(lái)描述就是


圖1.jpeg
圖2.jpeg

圖1表示的是一個(gè)正確的,圖二因?yàn)橛蚁碌男本€(xiàn)上出現(xiàn)了同樣的一個(gè)所以是不符合條件颗搂。
首先說(shuō)一下解題思路担猛。因?yàn)槭且粋€(gè)8*8的格子,又同時(shí)需要放八個(gè)棋子丢氢。所以我們第一個(gè)得到的信息是每一行有且僅有一個(gè)棋子毁习。因?yàn)樾本€(xiàn)部分影響的因素很多所以暫時(shí)是不能得到什么有效的訊息。如果我們首先就將斜線(xiàn)的部分都考慮進(jìn)去的話(huà)卖丸。這個(gè)干擾因素就會(huì)越來(lái)越多到最后我們只能選擇放棄纺且。既然不能一下從全局解決這個(gè)問(wèn)題那就只能將復(fù)雜問(wèn)題簡(jiǎn)單化,先從局部開(kāi)始著手稍浆。
首先我們從第一行開(kāi)始分析载碌,因?yàn)槭堑谝粋€(gè)棋子所以在第一行什么位置都是可以的猜嘱。但是為了后面的統(tǒng)一化,我們都是將棋子從最左邊開(kāi)始放嫁艇。比如我們將第一個(gè)棋子放在(0朗伶,0)位置。注意我這里是將整個(gè)棋盤(pán)看成一個(gè)長(zhǎng)度為8的二維數(shù)組步咪。左上角為(0论皆,0)位置。接下來(lái)我們?cè)诘诙械淖钭筮叿诺诙€(gè)棋子猾漫。注意這時(shí)候我們需要判斷這個(gè)位置是否符合條件点晴。也就是上下左右以及斜面都不能有棋子。就這樣以此類(lèi)推悯周。這個(gè)復(fù)雜的問(wèn)題就是:我在第每行放棋子的時(shí)候進(jìn)行以此判斷粒督,如果不符合條件自動(dòng)水平往右移動(dòng)一位,繼續(xù)判斷禽翼。直到我在第八行找到合適的位置時(shí)屠橄,表示已經(jīng)找到了一個(gè)符合條件的正確解。分析到這里闰挡,這個(gè)復(fù)雜的問(wèn)題是不是就已經(jīng)分解成锐墙,我只需要每次放棋子的時(shí)候判斷棋子的位置時(shí)候符合條件的一個(gè)遞歸問(wèn)題了。同時(shí)這個(gè)遞歸結(jié)束的條件就是在第八行找到合適的位置放下棋子就表示這一次尋找結(jié)束了长酗。

注意

這里我們要注意一個(gè)問(wèn)題:就是我們可能第一次放棋子的位置不對(duì)導(dǎo)致找不到最優(yōu)解贮匕。這時(shí)我們還需要考慮 回溯問(wèn)題 就是回退到上一個(gè)我們的位置繼續(xù)尋找。這樣才能保證找到所有的最優(yōu)解花枫。 接下來(lái)就是代碼來(lái)演示了:

/**
 在 8 X 8 的網(wǎng)格中刻盐,放入八個(gè)皇后(棋子),
 滿(mǎn)足的條件是劳翰,任意兩個(gè)皇后(棋子)都不能處于同一行敦锌、同一列或同一斜線(xiàn)上,問(wèn)有多少種擺放方式佳簸?
 */
public class Def {

    public static int[][] checkerboard = new int[8][8];//棋盤(pán)
    
    // 打印符合條件的棋子位置
    public static void print(){
        for(int i=0;i<checkerboard.length;i++){
            for(int j=0;j<checkerboard[i].length;j++){
                if(checkerboard[i][j] == 0){
                    System.out.print(checkerboard[i][j]+" ");
                }else{
                    System.out.print(checkerboard[i][j]+" ");
                }

            }
            System.out.println();
        }
    }
    // 檢查當(dāng)前棋子的位置是否符合條件
    public static Boolean check2(int x,int y){
        if(x>7 || x<0 || y<0 || y >7) return false;
        if(checkerboard[x][y] != 0 ) return  false;
        for(int i=0;i<8;i++){
            if(checkerboard[x][i] != 0) return false;
        }
        for(int i=0;i<8;i++){
            if(checkerboard[i][y] != 0) return false;
        }
        if(!recursion2(x-1,y-1,"leftTop")) return false;
        if(!recursion2(x-1,y+1,"leftDown")) return false;
        if(!recursion2(x+1,y+1,"rightDown")) return false;
        if(!recursion2(x+1,y-1,"rightTop")) return false;
        return true;
    }
    
    // 對(duì)斜線(xiàn)上的位置進(jìn)行檢查
    public static Boolean  recursion2(int x,int y,String direction){
        Boolean flag = true;
            switch (direction) {
                case "leftTop":
                    while (x>=0 && y>=0){
                        if(checkerboard[x][y]!=0) {
                            flag = false;
                            return flag;
                        }
                        x--;
                        y--;
                    }
                    break;
                case "leftDown":
                    while (x>=0 && y<=7){
                        if(checkerboard[x][y]!=0) {
                            flag = false;
                            return flag;
                        }
                        x--;
                        y++;
                    }
                    break;
                case "rightTop":
                    while (x<=7 && y>=0){
                        if(checkerboard[x][y]!=0) {
                            flag = false;
                            return flag;
                        }
                        x++;
                        y--;
                    }
                    break;
                case "rightDown":
                    while (x<=7 && y<=7){
                        if(checkerboard[x][y]!=0) {
                            flag = false;
                            return flag;
                        }
                        x++;
                        y++;
                    }
                    break;
            }
        return flag;

    }

    public static int count = 0;
    public static void add2(int x){
        // 滿(mǎn)足條件的棋子條件
        if(x == 8) {
            count++;
            print();
            System.out.println("=============================");
            return;
        }
        for(int i=0;i<8;i++){
            if(check2(x,i)){
                checkerboard[x][i] = 1;
                x++;// 這里++是推動(dòng)下一行
                add2(x);
                x--;// 注意這里很重要 這就是處理 回溯問(wèn)題 需要會(huì)到上一次的位置 
                checkerboard[x][i] = 0;//將上一次的記錄抹掉
            }
        }

    }
    public static void main(String[] args) {
        add2(0);
        System.out.println(count);
    }
}
結(jié)果

整個(gè)過(guò)程大概就是這樣了乙墙。代碼部分的注釋比較清楚,不明白的可以去看一下注釋生均。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末听想,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子马胧,更是在濱河造成了極大的恐慌汉买,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佩脊,死亡現(xiàn)場(chǎng)離奇詭異蛙粘,居然都是意外死亡垫卤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)出牧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)穴肘,“玉大人,你說(shuō)我怎么就攤上這事舔痕∑栏В” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵伯复,是天一觀(guān)的道長(zhǎng)慨代。 經(jīng)常有香客問(wèn)我,道長(zhǎng)边翼,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任鸣剪,我火速辦了婚禮组底,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘筐骇。我一直安慰自己债鸡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布铛纬。 她就那樣靜靜地躺著厌均,像睡著了一般。 火紅的嫁衣襯著肌膚如雪告唆。 梳的紋絲不亂的頭發(fā)上棺弊,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音擒悬,去河邊找鬼模她。 笑死,一個(gè)胖子當(dāng)著我的面吹牛懂牧,可吹牛的內(nèi)容都是我干的侈净。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼僧凤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畜侦!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起躯保,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤旋膳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后途事,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體溺忧,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咏连,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鲁森。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祟滴。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖歌溉,靈堂內(nèi)的尸體忽然破棺而出垄懂,到底是詐尸還是另有隱情,我是刑警寧澤痛垛,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布草慧,位于F島的核電站,受9級(jí)特大地震影響匙头,放射性物質(zhì)發(fā)生泄漏漫谷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一蹂析、第九天 我趴在偏房一處隱蔽的房頂上張望舔示。 院中可真熱鬧,春花似錦电抚、人聲如沸惕稻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)俺祠。三九已至,卻和暖如春借帘,著一層夾襖步出監(jiān)牢的瞬間蜘渣,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工肺然, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宋梧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓狰挡,卻偏偏與公主長(zhǎng)得像捂龄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子加叁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 我今天好不容易上了一次課倦沧,然后數(shù)據(jù)結(jié)構(gòu)老師給我們留大作業(yè),喪心病狂它匕,先解決一個(gè)叫八皇后的問(wèn)題展融。 題目背景: 【問(wèn)題...
    阿里高級(jí)軟件架構(gòu)師閱讀 2,975評(píng)論 1 5
  • 上午剛上班不久告希,突然收到一條短信:時(shí)間過(guò)得挺快的扑浸,都一年了,這一年里我學(xué)會(huì)了很多燕偶。當(dāng)初真的很感謝你喝噪,要不是你們,我...
    玲瓏雪ElieenGu閱讀 462評(píng)論 0 0
  • “兩個(gè)人的婚姻不但家庭上要門(mén)當(dāng)戶(hù)對(duì),精神上也要門(mén)當(dāng)會(huì)對(duì)伯诬⊥泶剑” 今天是老公四十二周歲的生日,想為他寫(xiě)點(diǎn)什么盗似。想了...
    沐源工作室閱讀 476評(píng)論 10 6
  • react的核心知識(shí)點(diǎn)虛擬domJSX語(yǔ)法單向數(shù)據(jù)綁定組件化 虛擬dom的概念 1.虛擬dom和dom的本質(zhì)區(qū)別:...
    獨(dú)步西行閱讀 268評(píng)論 0 0
  • 春天的約定 春節(jié)不知不覺(jué)的過(guò)完了哩陕,生機(jī)勃勃的春天悄悄的來(lái)了。鳥(niǎo)兒從南風(fēng)飛回來(lái)了...
    郭澤華2閱讀 155評(píng)論 0 2