走台阶 OR 台阶走——《狂人C》习题解答14(第三章习题4)
題目:
4.?有一段樓梯有6級臺階,規定每一步只能跨一級或兩級,要登上第6級臺階有幾種不同的走法?
?????這個題目從數學角度來看可能有一點難度,但一經點破也就沒什么難度了。
?????首先第1級臺階只有一種走法。第2級臺階有兩種走法,因為可以直接跨上,也可以從第1級跨上。
?????換句話說,由于登上第2級臺階可以從第0階(最初的狀態)也可以從第1階登上,所以
??????????登上第2級臺階的走法的數目 = 登上第0級臺階的走法的數目 + 登上第1級臺階的走法的數目
其中登上第0級臺階的走法的數目顯然為1種。?
?????這個道理就如同到某地有三條陸路兩條水路,那么到該地一共有五條路一樣。
?????后面各階走法的數目的求法和第2階的求法類似。
?????描述這個求解過程的代碼為:
#include <stdlib.h>
int main( void )
{
int num_of_step0 = 1 , num_of_step1 = 1 , num_of_step2 , ,
num_of_step3 , num_of_step4 , num_of_step5 , num_of_step6;
num_of_step2 = num_of_step1 + num_of_step0 ;
num_of_step3 = num_of_step2 + num_of_step1 ;
num_of_step4 = num_of_step3 + num_of_step2 ;
num_of_step5 = num_of_step4 + num_of_step3 ;
num_of_step6 = num_of_step5 + num_of_step4 ;
printf("登上第6級臺階有%d種不同的走法\n" , num_of_step6 );
system("PAUSE");
return 0;
}
?????這種寫法的缺點是變量太多,如果階數更多,就需要定義更多的變量。那樣的話即使不把人累死也會把人給笨死。
?????因為這種方法仿佛是自己從第2階走到第6階,如果走的階數很多,那確實很累人。
?????實際上,走臺階是從人的主觀出發的一種想法,這種情況關心有多少級臺階是很自然的想法;但是如果換一種情境,稍微發揮一點想象力的話,不難發現如果人不動讓臺階反方向"走",問題的本質是一樣的。這時你不會關心一共有多少級臺階,你只會也只需要關心后面的兩級臺階和當前面對的臺階。也就是?
??????????登上當前臺階走法的數目 = 登上后面第1級臺階走法的數目 + 登上后面第2級臺階走法的數目
?????不難看出,這是一種基于"相對"的思考方法和描述方法,而前面那種寫法則是基于"絕對"的思考方法和描述方法。
?????臺階反方向"走"一步之后,狀態就變了。后面第1級臺階變成了后面第2級臺階,可以描述為?
??????????登上后面第2級臺階走法的數目 = 登上后面第1級臺階走法的數目
?????而當前面對的臺階則變成了后面第1級臺階,因而
??????????登上后面第1級臺階走法的數目=當前臺階走法的數目
?????現在你會發現你要解決的是和剛才完全一樣的問題。后面的代碼可以如法炮制。?
?????反復解決同樣的問題是令人愉快的,這樣的代碼好寫也不容易錯,只要認真把第一次寫對,然后復制粘貼就可以了。?代碼為:
#include <stdlib.h>
int main( void )
{
int num_of_current_step , //當前面對臺階走法數目
num_of_passed_step1 , //后面第1級臺階走法數目
num_of_passed_step2 ; //后面第2級臺階走法數目
//在第0階時
num_of_current_step = 1 ; //根據分析
//在第1階時
num_of_passed_step1 = num_of_current_step ; //當前退后1階
num_of_current_step = 1 ; //根據分析
//在第2階時
num_of_passed_step2 = num_of_passed_step1 ; //退后1階
num_of_passed_step1 = num_of_current_step ; //退后1階
num_of_current_step = num_of_passed_step1
+ num_of_passed_step2 ; //當前等于后面兩階之和
//在第3階時 。從這里開始可以復制粘貼了
num_of_passed_step2 = num_of_passed_step1 ; //退后1階
num_of_passed_step1 = num_of_current_step ; //退后1階
num_of_current_step = num_of_passed_step1
+ num_of_passed_step2 ; //當前等于后面兩階之和
//在第4階時
num_of_passed_step2 = num_of_passed_step1 ; //退后1階
num_of_passed_step1 = num_of_current_step ; //退后1階
num_of_current_step = num_of_passed_step1
+ num_of_passed_step2 ; //當前等于后面兩階之和
//在第5階時
num_of_passed_step2 = num_of_passed_step1 ; //退后1階
num_of_passed_step1 = num_of_current_step ; //退后1階
num_of_current_step = num_of_passed_step1
+ num_of_passed_step2 ; //當前等于后面兩階之和
//在第6階時
num_of_passed_step2 = num_of_passed_step1 ; //退后1階
num_of_passed_step1 = num_of_current_step ; //退后1階
num_of_current_step = num_of_passed_step1
+ num_of_passed_step2 ; //當前等于后面兩階之和
printf("登上第6級臺階有%d種不同的走法\n" , num_of_current_step );
system("PAUSE");
return 0;
}
?????這種寫法無疑更加簡單也更強大,因為變量少,而且很容易擴展為解決其他階數同樣的問題。更主要的是后面幾段代碼可以通過復制粘貼不做任何修改簡單地完成。
?????可能有人覺得第2種寫法代碼太長,這個問題在后面學習了循環控制語句之后很容易解決。代碼的結構簡單是更重要的。第2段代碼由于是在反復做同樣的事(這恰恰是計算機的長處),所以結構是簡單的。而第一段代碼,復制粘貼后由于需要修改變量名,從某種意義上來說,結構在不斷變化,因而是復雜的。況且修改變量名很容易發生錯誤,這也可以視為更加復雜。?
?????只要有可能,盡量寫簡單的代碼是編程的一項基本原則,這就是所謂的KISS原則——Keep It Simple Stupid。
?????然而我們從前面不難看到,寫出簡單不易錯的代碼往往是需要多動一些腦筋的,而復雜容易錯的代碼則往往是不加思索一蹴而就的產物。
?????有句名言:把事情變簡單很復雜,把事情變復雜很簡單。
?????這話我們似乎同樣可以理解為寫代碼是簡單的,但在寫代碼之前的思考則是復雜的。
?????對于高手來說,一旦開始寫代碼,那就往往意味著代碼即將完成。看似簡單輕松完成的東西,其實寫之前在心里不知布局謀劃苦心經營了多久。?
?????初學者往往一拿到題目就立刻開始寫代碼,這是很不好的編程習慣,絕對不會寫出優秀的代碼。
轉載于:https://www.cnblogs.com/KBTiller/archive/2011/07/15/2107161.html
總結
以上是生活随笔為你收集整理的走台阶 OR 台阶走——《狂人C》习题解答14(第三章习题4)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客练习赛26 Dxor序列 (线性基
- 下一篇: CCPC-Wannafly Winter