這道題需要用到回溯算法,現在在這里先簡單的介紹一下這個算法:
回溯算法也叫試探法,它是一種系統地搜索問題的解的方法。回溯算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。用回溯算法解決問題的一般步驟為:
1、定義一個解空間,它包含問題的解。
2、利用適於搜索的方法組織解空間。
3、利用深度優先法搜索解空間。
4、利用限界函數避免移動到不可能產生解的子空間。
問題的解空間通常是在搜索問題的解的過程中動態產生的,這是回溯算法的一個重要特性。
首先,看一個簡單的程序;
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 1
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 3
首先第一個不難理解,第二個,首先進行三次遞歸,分別是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 }

