原創
問題描述:
有N階台階,每一步可以走1步台階或者2步台階,求出走到第N階台階的方法數。
解題思路:
- 類似於建立樹的過程
1 2
1 2 1 2
1 2 1 2 1 2 1 2
…….. ........
如上,建立一棵根節點為1和一棵根節點為2的二叉樹,分別表示台階第一步跨1步和跨2步,
第二層各有兩種選擇,分別是跨1步和2步,接下來的每一層都有這兩種選擇,如何跨
越的階數等於N,計數變量+1,如果大於N,返回繼續走其他路徑。
(由於n到45左右時數據已經爆炸,這種暴力遞歸法在n較大時系統出不來數據了)
1 #include<stdio.h> 2 3 int count; //計數變量 4 5 void sos(int n,int step) 6 { 7 if(step>n) //大於n,這種方法不行 8 return; 9 if(step==n) 10 { 11 count++; 12 return; 13 } 14 15 sos(n,step+1); //樹1 16 sos(n,step+2); //樹2 17 } 18 19 int main() 20 { 21 int n; 22 scanf("%d",&n); //n階台階 23 24 sos(n,0); 25 printf("%d",count); 26 return 0; 27 }
2. 動態規划法
有一個規律: F(n)= F(n-1)+ F(n-2);
F(n)表示當有n階台階時有F(n)種方法;比如F(1)= 1;F(2)= 2;F(3)= F(1)+ F(2)= 3;
下面我用我的思路盡可能讓大家理解這個公式:
1. 可以這樣想,需要跨越n層階梯,那么第一步我跨1層階梯,那么剩下n-1層階梯,跨越這n-1階台階的方法
就有F(n-1)方法; 同理,第一步跨2層階梯,那么跨越剩下的n-2層階梯就有F(n-2)種方法。
所以跨越n層階梯的方法數 F(n)= F(n-1)+ F(n-2);
2. 如果上面大家不理解,還可以這樣理解,假如我們已經知道了F(n-1)和F(n-2),求F(n);
在F(n-2)的基礎上,我們可以通過一次跨2層階梯到達第n層,也可以通過先跨1步,再跨1步的方式到達
第n層。 我們可以這樣理解,如果一次性跨2層階梯,我們只是在每一種跨越n-2層階梯方式的基礎上再加上
2就能到達第n層階梯了,所以方法還是F(n-2);
如果先跨1步,這樣加上原來的n-2步,就一共走了n-1步了,方法數就是F(n-1)了,然后再跨多1步,同
上,我們只是在每一種跨越n-1層階梯方式的基礎上再加上1就能到達第n層階梯了,所以方法還是F(n-1)。
希望這樣說大家能理解。
如有疑問和建議,非常歡迎大家發表評論。
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int sos(long long *arr,int n) 5 { 6 if(n<0) 7 return 0; 8 if(n==0 || n==1 || n==2) 9 return n; 10 11 if(arr[n-1]==0) //等於0表示沒有被算出 12 arr[n-1]=sos(arr,n-1); //沒有被算出,就先算出 13 14 if(arr[n-2]==0) //同理 15 arr[n-2]=sos(arr,n-2); 16 17 return arr[n-1]+arr[n-2]; //等到算出arr[n-1]和arr[n-2]后就可以算出arr[n]了 18 } 19 20 int main() 21 { 22 int n; 23 scanf("%d",&n); //輸入台階數 24 25 long long *arr; 26 arr=(long long *)malloc(sizeof(long long)*(n+1)); //分配n+1個空間 27 28 int i; 29 for(i=0;i<=n;i++) //數組全部元素置0 30 arr[i]=0; 31 32 printf("%I64d",sos(arr,n)); 33 34 free(arr); 35 return 0; 36 }
2018-04-06
