1.河內之塔
說明:河內之塔(Towers of Hanoi)是法國人M.Claus(Lucas)于1883年從泰國帶至法國的,河內為越戰(zhàn)時北越的首都,即現(xiàn)在的胡志明市;1883年法國數(shù)學家 EdouardLucas曾提及這個故事,據(jù)說創(chuàng)世紀時Benares有一座波羅教塔,是由三支鉆石棒(Pag)所支撐,開始時神在第一根棒上放置64個由上至下依由小至大排列的金盤(Disc),并命令僧侶將所有的金盤從第一根石棒移至第三根石棒,且搬運過程中遵守大盤子在小盤子之下的原則,若每日僅搬一個盤子,則當盤子全數(shù)搬運完畢之時,此塔將毀損,而也就是世界末日來臨之時。
解法:如果柱子標為ABC,要由A搬至C,在只有一個盤子時,就將它直接搬至C,當有兩個盤子,就將B當作輔助柱。如果盤數(shù)超過2個,將第三個以下的盤子遮起來,就很簡單了,每次處理兩個盤子,也就是:A->B、A ->C、B->C這三個步驟,而被遮住的部份,其實就是進入程式的遞回處理。事實上,若有n個盤子,則移動完畢所需之次數(shù)為2^n- 1,所以當盤數(shù)為64時,則所需次數(shù)為:264- 1 = 18446744073709551615為5.05390248594782e+16年,也就是約5000世紀,如果對這數(shù)字沒什幺概念,就假設每秒鐘搬一個盤子好了,也要約5850億年左右。
#include
void hanoi(intn, char A, char B, char C) {
if(n == 1) {
printf("Move sheet %d from %c to%cn", n, A, C);
}
else {
hanoi(n-1, A, C, B);
printf("Move sheet %d from %c to%cn", n, A, C);
hanoi(n-1, B, A, C);
}
}
int main() {
int n;
printf("請輸入盤數(shù):");
scanf("%d", &n);
hanoi(n, 'A', 'B', 'C');
return 0;
}
2.AlgorithmGossip: 費式數(shù)列
說明:Fibonacci為1200年代的歐洲數(shù)學家,在他的著作中曾經(jīng)提到:「若有一只免子每個月生一只小免子,一個月后小免子也開始生產(chǎn)。起初只有一只免子,一個月后就有兩只免子,二個月后有三只免子,三個月后有五只免子(小免子投入生產(chǎn))......。
如果不太理解這個例子的話,舉個圖就知道了,注意新生的小免子需一個月成長期才會投入生產(chǎn),類似的道理也可以用于植物的生長,這就是Fibonacci數(shù)列,一般習慣稱之為費氏數(shù)列,例如以下: 1、1 、2、3、5、8、13、21、34、55、89......
解法:依說明,我們可以將費氏數(shù)列定義為以下:
fn = fn-1 + fn-2 if n> 1
fn = n if n = 0, 1
#include
#include
#define N 20
int main(void) {
int Fib[N] ={0};
int i;
Fib[0] = 0;
Fib[1] = 1;
for(i = 2; i< N; i++)
Fib[i] =Fib[i-1] + Fib[i-2];
for(i = 0; i< N; i++)
printf("%d", Fib[i]);
printf("n");
return 0;
}
3. 巴斯卡三角形
#include
#define N 12
long combi(intn, int r){
int i;
long p = 1;
for(i = 1; i <= r; i++)
p = p * (n-i+1) / i;
return p;
}
void paint() {
int n, r, t;
for(n = 0; n <= N; n++) {
for(r = 0; r <= n; r++) {
int i;/* 排版設定開始 */
if(r == 0) {
for(i = 0; i <= (N-n); i++)
printf(" ");
}else {
printf(" ");
} /* 排版設定結束 */
printf("%3d", combi(n,r));
}
printf("n");
}
}
4.AlgorithmGossip: 三色棋
說明:三色旗的問題最早由E.W.Dijkstra所提出,他所使用的用語為Dutch Nation Flag(Dijkstra為荷蘭人),而多數(shù)的作者則使用Three-ColorFlag來稱之。
假設有一條繩子,上面有紅、白、藍三種顏色的旗子,起初繩子上的旗子顏色并沒有順序,您希望將之分類,并排列為藍、白、紅的順序,要如何移動次數(shù)才會最少,注意您只能在繩子上進行這個動作,而且一次只能調換兩個旗子。
解法:在一條繩子上移動,在程式中也就意味只能使用一個陣列,而不使用其它的陣列來作輔助,問題的解法很簡單,您可以自己想像一下在移動旗子,從繩子開頭進行,遇到藍色往前移,遇到白色留在中間,遇到紅色往后移,如下所示:
只是要讓移動次數(shù)最少的話,就要有些技巧:
如果圖中W所在的位置為白色,則W+1,表示未處理的部份移至至白色群組。
如果W部份為藍色,則B與W的元素對調,而B與W必須各+1,表示兩個群組都多了一個元素。
如果W所在的位置是紅色,則將W與R交換,但R要減1,表示未處理的部份減1。
注意:B、W、R并不是三色旗的個數(shù),它們只是一個移動的指標;什幺時候移動結束呢?一開始時未處理的R指標會是等于旗子的總數(shù),當R的索引數(shù)減至少于W的索引數(shù)時,表示接下來的旗子就都是紅色了,此時就可以結束移動,如下所示:
#include
#include
#include
#define BLUE 'b'
#define WHITE'w'
#define RED 'r'
#define SWAP(x,y) { char temp;
temp = color[x];
color[x] = color[y];
color[y] = temp; }
int main() {
char color[] = {'r', 'w', 'b', 'w', 'w',
'b', 'r', 'b', 'w', 'r','