遞推之猴子爬山
阿新 • • 發佈:2019-02-08
遞推是利用問題本身所具有的遞推關係求解問題的方法。所謂遞推,是在命題歸納時,可以由數量分別為n-k,…,n-1的情形推得數量為n的情形,或者反過來由數量分別為i+k,…,i+1的情形推出數量為i的情形。
我們大家比較熟悉的應該就是斐波那契數列了;這裡給大家講一下稍微複雜一點的遞推——猴子爬山問題。
一個猴子在一座有30級臺階的小山坡上跳躍,猴子一步可以跳躍1級或者3級,試求上山一共有多少種不同的走法?
設爬k級臺階的不同爬法有f(k)種,
(1)尋找f(k)的遞推關係。上山最後一步到達第30級臺階完成上山,共有f(30)種不同的走法;到第30級臺階之前呢?無非是在第29級(上跳1級就行了),有f(29)種;或者位於第27級(上跳3級就行了),有f(27)種;於是f(30)=f(29)+f(27);
以此類推,有以下遞推關係:
f(k)=f(k-1)+f(k-3) (k>3);
(2)確定初始條件
f(1)=1;
f(2)=2;
f(3)=2;
(3)code如下:
int main()
{
int k,n;
long f[1000];
printf("請輸入臺階總數n:");
scanf("%d",&n);
f[1]=1;
f[2]=2;
f[3]=3;
for(int k=4;k<=n;k++)
f[k]=f[k-1]+f[k-3];
printf("s=%1d",f[n]);
}
問題引申:設爬n級臺階,一步有m種跨法,一步跨多少級均從鍵盤輸入,求共有多少種不同的爬法。
這是一個分級遞推問題,設爬山t級臺階的不同爬法為f(t),從鍵盤輸入的m個整數分別為x(1 ),x(2),x(3),.........,x(m) (約定x(1)<x(2)<...x(m)<n)
首先探討f(t)的遞推關係:
當t<x(1)時,f(t)=0,f(x(1))=1 (初始條件)
當x(1)<t<=x(2)時,第1級遞推,f(t)=f(t-x(1))
當x(2)<t<=x(3)時,第2級遞推,f(t)=f(t-x(1))+f(t-x(2))
.......
一般地,當x(k)<t<=x(k+1),k=1,2,,...,m-1, 有第k級遞推:
f(t)=f(t-x(1))+f(t-x(2 ))+....+f(t-x(k))
當x(m)<t時,有第m級遞推:
f(t)=f(t-x(1))+f(t-x(2))+...+f(t-x(m))
當t=x(2)或x(3)...x(m)時,還要加1,因為t本身就是一個一步到位的爬法,則 f(t)=f(t)+1;
我們所求的目標就是
f(n)=f(n-x(1))+f(n-x(2))+...+f(n-x(m))
再設計遞推的過程中可以把臺階數記為陣列x(m+1)
main()
{
int i,j,k,m,n,t,x[10];
long f[200];
printf("請輸入總檯階數n:");
scamf("%d",&n);
printf("一次有幾種跳法:");
scanf("%d",&m);
printf("請從小到大輸入一步跳幾級.\n");
for(i=1;i<=m;i++)
{
printf("第%d個一步可以跳級數:",i);
scanf("%d",&x[i]);
}
for(i=1;i<=x[1]-1;i++)
f[i]=0; //確定初始條件
x[m+1]=n;
f[x[1]]=1; //初始條件
for(k=1;k<=m;k++) //一共m種爬法,實現對每一種爬法的累加
for(t=x[k]+1;t<=x[m+1];t++)
{
f[t]=0;
for(j=1;j<=k;j++)
f[t]=f[t]+f[t-x[j]];//按公式實現累加
if(t==x[m+1])
f[t]=f[t]+1;
}
printf("共有不同的爬法種數為:%d",f[n]-1); //因為用到了x[m+1],將他也看成了一步走法,所以減1