這道題須要用到回溯算法,如今在這裏先簡單的介紹一下這個算法:算法
回溯算法也叫試探法,它是一種系統地搜索問題的解的方法。回溯算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。用回溯算法解決問題的通常步驟爲:函數
一、定義一個解空間,它包含問題的解。spa
二、利用適於搜索的方法組織解空間。code
三、利用深度優先法搜索解空間。blog
四、利用限界函數避免移動到不可能產生解的子空間。遞歸
問題的解空間一般是在搜索問題的解的過程當中動態產生的,這是回溯算法的一個重要特性。io
首先,看一個簡單的程序;for循環
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void function(int a) 5 { 6 if (a > 0) 7 { 8 printf("%d\n", a); 9 function(a - 1); 10 } 11 } 12 13 int main(void) 14 { 15 int a = 3; 16 function(3); 17 system("PAUSE"); 18 return 0; 19 }
輸出:3 2 1function
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void function(int a) 5 { 6 if (a > 0) 7 { 8 function(a - 1); 9 printf("%d\n",a); 10 } 11 } 12 13 int main(void) 14 { 15 int a = 3; 16 function(3); 17 system("PAUSE"); 18 return 0; 19 }
輸出:1 2 3class
首先第一個不難理解,第二個,首先進行三次遞歸,分別是function(2),function(1),function(0)=>a=3,a=2,a=1;當到a=1遞歸執行結束,就會接着往下執行,執行printf,因此此時輸出1,而後,返回到上一級遞歸,function(1),執行結束後,再次執行printf,輸出1...
八皇后問題:
八皇后問題,是一個古老而著名的問題,是回溯算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認爲有76種方案。1854年在柏林的象棋雜誌上不一樣的做者發表了40種不一樣的解,後來有人用圖論的方法解出92種結果。計算機發明後,有多種計算機語言能夠解決此問題。
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define max 8//定義最大方格 5 6 int a[max],sum=0;//定義全局變量 7 8 int check_function(int n) { //檢查當定一個點時,以行爲單位掃描(a[n]爲橫座標)遍歷其餘列的位置是否能知足要求 9 int i; 10 for(i=0; i<n; i++)/*i<n,而不是i<max,這裏用法是:首先定的一個點爲起始點,這個點確定正確,而後對下列掃描,找到,和上一列定那個點一塊兒知足條件的點,接着第三第四列同樣,到第八列(max),又找到點時,這時候知足第30行代碼的輸出條件,輸出,找到一組 11 ,接着第26~28行代碼,至關於將定點縱座標加一,進行移位操做,而後到check_function函數中進行與上面相似的操做*/ 12 { 13 if(a[i]==a[n]||abs(a[i]-a[n])==abs(i-n)) { //a[i]==b[n]表示在同一排的狀況,後者爲在同一對角線上(記住abs求絕對值函數) 14 return 1;//不知足條件返回1 15 } 16 } 17 return 0;//知足條件返回0 18 19 } 20 21 int func(int n) { //定義一個進行對定點改變與輸出結果的函數 22 int i,t; 23 for(i = 0; i < max; i++) { 24 a[n]=i;//假設的點,當每次知足條件返回1時,會再次進行上面的for循環,對i進行加一操做,至關於對縱座標操做,下移一位 25 if(check_function(n)==0) { //結合上一個給a[n]賦值,經過判斷是否符合條件,讓a[n]的值爲每一列知足條件的值(縱座標),n爲橫座標 26 if(n==max-1) { //max-1 說的是最後一列,當橫座標數等於最後一列,且知足了檢驗,就說明這是一組中的最後一個,因而輸出知足條件的a[n] 27 for(t=0; t<n; t++) 28 printf("(%d,%d),",t,a[t]);//這樣打印的緣由:到這裏,每一個a[n]實際是知足條件的位置 29 printf("\n"); 30 sum++; 31 } else { 32 func(n+1);//若知足了檢驗,卻不知足是最後一項,則說明這只是一組中的一個,且不是最後一個,由於推出結果是按列進行掃描,因此,橫座標向後移一位 33 } 34 } 35 } 36 } 37 38 39 int main(void) { 40 func(0);//定橫座標爲零 41 printf("sum=%d\n",sum);//打印出擺放方式數 42 return 0; 43 }