程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 一步一步寫算法(之八皇後)

一步一步寫算法(之八皇後)

編輯:關於C語言

 

【 聲明:版權所有,歡迎轉載,請勿用於商業用途。  聯系信箱:feixiaoxing @163.com】

 

 

 

 

    八皇後是一道很具典型性的題目。它的基本要求是這樣的:在一個8*8的矩陣上面放置8個物體,一個矩陣點只允許放置一個物體,任意兩個點不能在一行上,也不能在一列上,不能在一條左斜線上,當然也不能在一條右斜線上。

 

    初看到這道題目,大家的第一印象是遍歷,但是經過實踐之後發現遍歷其實不好寫,而且復雜度很低。不僅需要遍歷8*8*8*8*8*8*8*8*8 = 2^24次數據,還要判斷各種條件,實際的計算復雜度還要比較這個高。其實我們仔細看一看,這中間很多的計算其實很多是不需要的,因為如果我們在某一行沒有可以插入的數據的話,那麼這後面的行其實就不用考慮了。也就是說,我們只有在保證前面 插入的物體都合法有效的情況下,才能進行下一次的物體插入。無謂的遍歷只會是無用功。

 

   那麼,我們應該怎麼做呢?其實步驟不太難:

 

    (1)在第n行尋找可以插入的位置,中間涉及到位置合法性的判斷

 

    (2)如果沒有可以插入的位置,返回

 

    (3)如果有可以插入的位置, 插入數據。此時再判斷是否已經是最後一行,如果是,打印輸出返回;反之繼續對下一行數據進行試探處理。

 

    有了上面的步驟,我們就可以書寫代碼了。老規矩,朋友們可以自己先嘗試一下。

 

    a)定義全局堆棧和打印函數

 

 

static int gEightQueen[8] = {0}; 

static int gCount = 0; 

 

void print() 

    int outer; 

    int inner; 

 

    for(outer = 0; outer <8; outer ++){ 

        for(inner = 0; inner < gEightQueen[outer]; inner ++) 

            printf("* "); 

 

        printf("# "); 

 

        for(inner = gEightQueen[outer] + 1; inner < 8; inner ++) 

            printf("* "); 

 

        printf("\n"); 

    } 

 

    printf("=====================================\n"); 

static int gEightQueen[8] = {0};

static int gCount = 0;

 

void print()

{

       int outer;

       int inner;

 

       for(outer = 0; outer <8; outer ++){

              for(inner = 0; inner < gEightQueen[outer]; inner ++)

                     printf("* ");

 

              printf("# ");

 

              for(inner = gEightQueen[outer] + 1; inner < 8; inner ++)

                     printf("* ");

 

              printf("\n");

       }

 

       printf("=====================================\n");

}

    b)添加位置合法性的函數判斷

 

 

int check_pos_valid(int loop, int value) 

    int index; 

    int data; 

 

    for(index = 0; index < loop; index ++){ 

        data = gEightQueen[index]; 

 

        if(value == data) 

            return 0; 

 

        if((index + data) == (loop + value)) 

            return 0; 

 

        if((index - data) == (loop - value)) 

            return 0; 

    } 

 

    return 1; 

int check_pos_valid(int loop, int value)

{

       int index;

       int data;

 

       for(index = 0; index < loop; index ++){

              data = gEightQueen[index];

 

              if(value == data)

                     return 0;

 

              if((index + data) == (loop + value))

                     return 0;

 

              if((index - data) == (loop - value))

                     return 0;

       }

 

       return 1;

}    c) 八皇後遍歷

 

 

void eight_queen(int index) 

    int loop; 

 

    for(loop = 0; loop < 8; loop++){ 

        if(check_pos_valid(index, loop)){ 

            gEightQueen[index] = loop; 

 

            if(7 == index){ 

                gCount ++, print(); 

                gEightQueen[index] = 0; 

                return; 

            } 

             

            eight_queen(index + 1); 

            gEightQueen[index] = 0; 

        } 

    } 

void eight_queen(int index)

{

       int loop;

 

       for(loop = 0; loop < 8; loop++){

              if(check_pos_valid(index, loop)){

                     gEightQueen[index] = loop;

 

                     if(7 == index){

                            gCount ++, print();

                         gEightQueen[index] = 0;

                            return;

                     }

                    

                     eight_queen(index + 1);

                     gEightQueen[index] = 0;

              }

       }

}

總結:

 

    (1)迭代遞歸是編程的難點,需要自己好好實踐,看別人寫一百遍,不如自己寫一遍

 

    (2)遞歸的時候務必注意函數return的出口

 

    (3)遞歸函數中語句的順序不要隨意更換

 

    (4)遞歸函數中注意數據的保存和恢復

 

    (5)遞歸函數也要驗證,可以用程序驗證法,也可以用其他函數的結果來驗證

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved