樓梯有n階臺階,上樓可以一步上1階,2階,3階,編程序計算共有多少種不同的走法?

題目:樓梯有n階臺階,上樓可以一步上1階,2階,3階,編程序計算共有多少種不同的走法

對於這樣一個問題,

思路:設n階臺階的走法數爲f(n)。如果只有1個臺階,走法有1種(一步上1個臺階),即f(1)=1;如果有2個臺階,走法有2種(一種是上1階,再上1階,另一種是一步上2階),即f(2)=2;如果有3個臺階,走法有4種(一種每次1階,共一種;另一種是2+1,共兩種;第三種是3,共1種),即f(3)=4;

當有n個臺階(n>3)時,我們縮小問題規模,可以這樣想:最後是一步上1個臺階的話,之前上了n-1個臺階,走法爲f(n-1)種,而最後是一步上2個臺階的話,之前上了n-2個臺階,走法爲f(n-2)種,故而f(n)=f(n-1)+f(n-2)。列出的遞歸方程爲:f(1)=1;f(2)=2;

f(3)=4;

if(n==1)

return 1;

else if(n==2)

return 2;

else if(n==3)

return 4;

else

return  f(n-1)+f(n-2)+f(n-3),n>3

最後一步可能是從第n-1階往上走1階、從n-2階往上走2階,或從第n-3階往上走3階。因此,抵達最後一階的走法,其實就是抵達這最後三階的方式的總和。

解決方法1:按照遞歸的思想;但運算時間很長

int countWays (int n)
{if (n<0)
   return 0;
if (n==0)
   return 1;
else
  {
  return countWays(n-1)+countWays(n-2)+countWays(n-3);
 }
}   


解決方法2:採用動態規劃的思想 優化,

當一個問題可以分解成若干重複的子問題時,運用動態規劃的思想:

只需要將子問題求解一次,以後再遇到,直接調用,所以我們新建一個數組用於存儲子問題的結果:
 
將數組元素初始爲零,若爲新的子問題,我們求解,並把結果賦給對應的數組元素;這樣當我們再次遇到相同的子問題,就可以直接調用了。
int countWaysDP(int n, dp[])
{ 
if (n<0)
   return 0;
if (n==0)
   return dp[n];
if (dp[n]>0)
   return dp[n]; //如果大於0  說明這個子問題已經計算過,直接調用數組
else 
{ dp[n]=countWays[n-1,dp]+countWays[n-2,dp]+countWays[n-3,dp];  //否則 還需計算該數組
return dp[n];
}
}
接下來貼上實際運行代碼吧;
#include<iostream>

using namespace std;
const int MAX=1000;
int countWays(int n)
{if (n<0)
	return 0;
if (n==0)
   return 1;
else
  {
  return countWays(n-1)+countWays(n-2)+countWays(n-3);
 }
} 

int countWaysDP(int n, int dp[])
{ 
if (n<0)
   return 0;
if (n==0)
   return 1;
if (dp[n]>0)
   return dp[n]; //如果大於0  說明這個子問題已經計算過,直接調用數組
else 
{	dp[n]=countWaysDP(n-1,dp)+countWaysDP(n-2,dp)+countWaysDP(n-3,dp);  //否則 還需計算該數組
	return dp[n];
}
}
int main()
{
	int m[MAX]={0};
//	int m[MAX]; 
	for(int i=1;i<10;i++)
		cout<<countWaysDP(i,m)<<endl;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章