八皇后問題

八皇后問題:在8*8的棋盤上放置8個(gè)皇后,保證任意兩個(gè)皇后之間不能相互攻擊。(即沒有兩個(gè)皇后是在同一行、同一類粘都、或者同一對角線上)

  1. 計(jì)算出8皇后或者N皇后可能的所有擺放結(jié)果。其中8皇后共計(jì)有92種不同的解刷袍。
  2. 打印顯示出來其中的一種擺放結(jié)果或者所有的結(jié)果。

1. 回溯法:

回溯法:即試探法樊展,系統(tǒng)的搜索所有解的方法呻纹。具體思想:從一條路往前走,能進(jìn)則進(jìn)专缠,不能進(jìn)則退出來雷酪,換條路再走。解決八皇后問題的經(jīng)典算法涝婉。

偽代碼如下:

  1. 將棋盤存到一個(gè)N*N的矩陣中(8*8)哥力,二維數(shù)組。
  2. 算法開始墩弯,清空棋盤吩跋,當(dāng)前行設(shè)為第一行,當(dāng)前列設(shè)為第一列渔工。
  3. 在當(dāng)前行當(dāng)前列的位置是否滿足條件:經(jīng)過這一點(diǎn)的行锌钮、列、以及兩條斜線上沒有其他皇后引矩。若滿足:轉(zhuǎn)到步驟4梁丘;若不滿足,轉(zhuǎn)到步驟5旺韭。
  4. 滿足步驟3的條件:在當(dāng)前位置放置一個(gè)皇后氛谜,分以下情況:
  1. 若當(dāng)前行不是最后一行,當(dāng)前行設(shè)為下一行区端, 當(dāng)前列設(shè)為當(dāng)前行的第一個(gè)待測位置(不一定是第一個(gè)位置)值漫;轉(zhuǎn)到步驟3。
  2. 如果是最后一行珊燎,記錄下這個(gè)解惭嚣。記錄之后遵湖,若當(dāng)前不是最后一列,當(dāng)前列設(shè)為下一列晚吞;若當(dāng)前列是最后一列延旧,即最后一列,回溯槽地,清空當(dāng)前行迁沫,然后當(dāng)前行設(shè)為上一行,當(dāng)前列設(shè)為當(dāng)前行的下一個(gè)待測位置捌蚊。
  1. 不滿足步驟3的條件集畅,分以下情況:
  1. 如果當(dāng)前列不是最后一列,當(dāng)前列設(shè)為下一列缅糟,繼續(xù)步驟3挺智。
  2. 如果當(dāng)前列是最后一列,回溯窗宦,即赦颇,若當(dāng)前行已經(jīng)是第一行了,算法退出赴涵,否則媒怯,清空當(dāng)前行及以下各行的棋盤,然后髓窜,當(dāng)前行設(shè)為上一行扇苞,繼續(xù)步驟5。

算法改進(jìn):把棋盤存儲(chǔ)為一個(gè)二維數(shù)組寄纵,然后需要在第i行第j列放置皇后時(shí)鳖敷,根據(jù)問題的描述,首先判斷是在第i行是否有皇后擂啥,由于每行只有一個(gè)皇后哄陶,這個(gè)判斷也可以省略,然后判斷第j列是否有皇后哺壶,這個(gè)也很簡單屋吨,最后需要判斷在同一斜線上是否有皇后,按照該方法需要判斷兩次山宾,正對角線方向和負(fù)對角線方向至扰。相對較為復(fù)雜。
若把棋盤存儲(chǔ)為一個(gè)N維數(shù)組q[N]资锰,數(shù)組中第i個(gè)元素的值代表第i行的皇后所在列的位置敢课,這樣便可以把問題的空間規(guī)模壓縮為一維O(N),在判斷是否沖突時(shí)也很簡單,首先每行只有一個(gè)皇后直秆,且在數(shù)組中只占據(jù)一個(gè)元素的位置濒募,行沖突就不存在了,其次是列沖突圾结,判斷一下是否有a[i]與當(dāng)前要放置皇后的列j相等即可瑰剃。至于斜線沖突,通過觀察可以發(fā)現(xiàn)所有在斜線上沖突的皇后的位置都有規(guī)律即它們所在的行列互減的絕對值相等筝野,即| row – i | = | col – a[i] | 晌姚。這樣某個(gè)位置是否可以放置皇后的問題已經(jīng)解決。

1. 遞歸實(shí)現(xiàn)

代碼如下

//八皇后問題解法
public class Queen {
      static int count=0;  //統(tǒng)計(jì)解的個(gè)數(shù)
      static int N = 8;      //皇后個(gè)數(shù):8
      static int [] q = new int[N];  
//大小為8的數(shù)組:數(shù)組下標(biāo)表示:row歇竟,數(shù)組[i]對應(yīng)內(nèi)容:col挥唠。
      public static void print()
      {//打印解的坐標(biāo)位置及圖像
          for(int i=0;i<N;i++)
              System.out.println(i+" "+q[i]);
          for(int i=0;i<N;i++)
          {
              System.out.print("|");
              for(int j=0;j<N;j++)
              {
                  if(j==q[i])
                      System.out.print("Q|");
                  else
                      System.out.print(" |");
              }
              System.out.println();
          }
      }
      public static boolean canPlace(int i,int j)
      {//判斷坐標(biāo)(i,j)處是否可以放置皇后
          for(int k=0;k<i;k++)
          {
              if(q[k]==j||Math.abs(i-k)==Math.abs(j-q[k]))
                  return false;
          }
          return true;
      }
    public static void queen(int row)
    {//遞歸,從第row行開始循環(huán)每一列
        if(row==N)
        {
            count++;
            if(count==1)
            print();
        }
        else
        {
            for(int j=0;j<N;j++)
            {
                if(canPlace(row,j))
                {
                    q[row]=j;
                    queen(row+1);
                }
            }
        }
    }
  public static void main(String[] args) {
      for(int i=0;i<N;i++)  //初始化
      { q[i]=-1;}
      queen(0);
      System.out.println(count);
}
}
2. 非遞歸實(shí)現(xiàn)
public class Queen {
    static int N=8;
    static int[]q=new int[N];
    static int count=0;
     public static void print()
      {
          for(int i=0;i<N;i++)
              System.out.println(i+" "+q[i]);
          for(int i=0;i<N;i++)
          {
              System.out.print("|");
              for(int j=0;j<N;j++)
              {
                  if(j==q[i])
                      System.out.print("Q|");
                  else
                      System.out.print(" |");
              }
              System.out.println();
          }
      }
      public static boolean canPlace(int i,int j)
      {
          for(int k=0;k<i;k++)
          {
              if(q[k]==j||Math.abs(i-k)==Math.abs(j-q[k]))
                  return false;
          }
          return true;
      }
    public static void queen()
    { 
        int row=0,col=0;
        while(row<N)
        {
            while(col<N)
            {
                if(canPlace(row,col))
                {
                    q[row]=col;
                    col=0;
                    break;
                }
                else
                {
                    ++col;
                }
            }
            if(col==N)//q[row]==-1
            {
                if(row==0)
                    break;
                else
                {
                    --row;
                    col=q[row]+1;
                    q[row]=-1;  //把上一行皇后的位置清除焕议,重新探測
                    continue;
                }
            }
            if(row==N-1)
            {
                count++;
                if(count==1)
                    print();
                col=q[row]+1;
                q[row]=-1;
                continue;
            }
            ++row;
        }
    }
  public static void main(String[] args) {
    for(int i=0;i<N;i++)//初始化
       q[i]=-1;
    queen();
    System.out.println(count);
}
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宝磨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盅安,更是在濱河造成了極大的恐慌懊烤,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宽堆,死亡現(xiàn)場離奇詭異,居然都是意外死亡茸习,警方通過查閱死者的電腦和手機(jī)畜隶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來号胚,“玉大人籽慢,你說我怎么就攤上這事∶ㄐ玻” “怎么了箱亿?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長弃秆。 經(jīng)常有香客問我届惋,道長,這世上最難降的妖魔是什么菠赚? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任脑豹,我火速辦了婚禮,結(jié)果婚禮上衡查,老公的妹妹穿的比我還像新娘瘩欺。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布俱饿。 她就那樣靜靜地躺著歌粥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拍埠。 梳的紋絲不亂的頭發(fā)上失驶,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音械拍,去河邊找鬼突勇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坷虑,可吹牛的內(nèi)容都是我干的甲馋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼迄损,長吁一口氣:“原來是場噩夢啊……” “哼定躏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芹敌,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對情侶失蹤痊远,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后氏捞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碧聪,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年液茎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逞姿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捆等,死狀恐怖滞造,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情栋烤,我是刑警寧澤谒养,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站明郭,受9級(jí)特大地震影響买窟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜达址,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一蔑祟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沉唠,春花似錦疆虚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽罢屈。三九已至,卻和暖如春篇亭,著一層夾襖步出監(jiān)牢的瞬間缠捌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工译蒂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留曼月,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓柔昼,卻偏偏與公主長得像哑芹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子捕透,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • 八皇后問題問題描述:八皇后問題乙嘀,是一個(gè)古老而著名的問題末购,是回溯算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾...
    藥藥耀耀閱讀 2,076評(píng)論 0 0
  • 問題描述: 八皇后問題虎谢,是一個(gè)古老而著名的問題盟榴,是回溯算法的典型案例:在8X8格的國際象棋棋盤上擺放八個(gè)皇后,使其...
    HeartGo閱讀 406評(píng)論 0 3
  • 問題描述 會(huì)下國際象棋的人都很清楚:皇后可以在橫婴噩、豎曹货、斜線上不限步數(shù)地吃掉其他棋子。如何將8個(gè)皇后放在棋盤上(有8...
    指尖極光閱讀 1,001評(píng)論 0 0
  • 白殊晏:親愛的讳推,又是一個(gè)愉快的周末,遠(yuǎn)在大洋彼岸的你正在干什么呢玩般?最近忙著各種學(xué)校的事情银觅,鑒于之前腦殘的一下子選了...
    Wonderland閱讀 207評(píng)論 0 1
  • ?這是奇小娜每天一篇原創(chuàng)文章的第31篇 一直把自己定義為“文藝女青年在創(chuàng)業(yè)”匀伏,聽起來挺別致的調(diào)調(diào)洒忧,但是仔細(xì)一咂摸,...
    奇小娜閱讀 784評(píng)論 0 51