C++——經典八後問題解析

這是我應聘如今這家公司的面試題,當時沒作好,如今網上這個問題的代碼已經不少了,問題也很透徹,排除由於棋盤的對稱性帶來的對稱解,總共92種解法。ios

 

八後問題最多見的解法就是遍歷法,一個八叉的遍歷問題具體操做以下:面試

 

因爲這個問題確定是每行有一個後,把起始設爲第一行算法

1.從第一列開始,放下一個後。oop

2.轉移到第二行,從第一列,防下一個後,檢驗是否與前面衝突,若衝突,轉到下一列;若不衝突,轉移到下一行。以此類推。this

 

遍歷算法:

這個問題是一個典型的嵌套循環, 從第一行開始,執行8次循環,從第1列到第7列。——第一層循環spa

  在第一層循環中,一旦成功放置旗子,則進入第二層循環,執行8次,從第1列到第7列,放置棋子前,要檢驗是否與已放置旗子衝突,若衝突,到下一列。——第二層循環code

    在第二層循環中,一旦成功放置旗子,則進入第三層循環,執行8次,從第1列到第7列,放置棋子前,要檢驗是否與已放置旗子衝突,若衝突,到下一列。——第三層循環blog

      在第三層循環中,一旦成功放置旗子,則進入第四層循環,執行8次,從第1列到第7列,放置棋子前,要檢驗是否與已放置旗子衝突,若衝突,到下一列。——第四層循環io

                                      .(從第五行開始可能會出現全行都衝突的狀況,這時候會跳出循環,進入到上一層循環的下一列,而後再回到這層循環)class

                                      .

                                      .

                            當到第七行後,如有不衝突的位置,則直接打印。

衝突檢測:

把衝突檢測包裝在方法裏才能很好的兼容循環,那麼如何才能最快的檢驗當前點(current_x,current_y),與現有的各個點(exist_x,exist_y)衝突呢,

首先一點就是,當我在循環中判斷當前點是否衝突時,我只需判斷當前行以前的各行便可,不會出現同行的狀況。

因此判斷的第一點就是是否同列:if(current_y==exist+y)

判斷的第二點就是斜線方向了,斜線兩個方向(current_x-current_y==exist_x-exisy_y) 和(current_x+current_y==exist_x+exisy_y)

這三個條件都不知足,纔算不衝突,繼續進入循環。

 

代碼以下:

 1 // 8-Queen_project.cpp : 定義控制檯應用程序的入口點。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include<iostream>
 6 using namespace std;
 7 
 8 static int result_array[8] = { 0 }, total_count = 0;
 9 void print()                                //打印
10 {
11     for (int i = 0; i < 8; i++)
12     {
13         for (int j = 0; j < result_array[i]; j++)
14             cout << " ";
15         cout << result_array[i] << endl;
16     }
17     cout << "--------\n";
18 }
19 int confliction(int c_row, int c_column)
20 {
21     int this_row;
22     int this_column;
23     for (this_row = 0; this_row < c_row; this_row++) //只檢驗上面的行
24     {
25         this_column = result_array[this_row];
26         if (c_column == this_column)
27             return 0;
28         if ((this_row + this_column) == (c_row + c_column))
29             return 0;
30         if ((this_row - this_column) == (c_row - c_column))
31             return 0;
32     }
33     return 1;
34 }
35 void loop(int row) // 參數就是行數
36 {
37     int column;
38     for (column = 0; column < 8; column++)//下面全部級的循環都結束,進入下一列
39     {
40         if (confliction(row, column))
41         {
42             result_array[row] = column;
43             if (row == 7)     //到最後一行打印
44             {
45                 total_count++, print();
46                 result_array[row] = 0;
47                 return;
48             }
49             loop(row + 1); //進入下一行循環
50             result_array[row] = 0;
51         }
52     }
53 }
54 int main(int argc, char*argv[])
55 {
56     loop(0);
57     cout << "total=" << total_count << endl;
58     return 0;
59 }

結果以下,92種能夠所有打印出來:

結果中數字表明列數。

相關文章
相關標籤/搜索