所謂遞推,是指從已知的初始條件出發,依據某種遞推關係,逐次推出所要求的各中間結果及最後結果。其中初始條件或是問題本身已經給定,或是通過對問題的分析與化簡後確定。關於遞推的知識可以參閱本博客中隨筆“遞推(一):遞推法的基本思想”。
HDU 2044~2050這7道題是針對初學者進行遞推學習的專項練習,下面給出它們的AC程序供參考。
HDU 2044:一隻小蜜蜂
不妨將圖示的蜂箱結構看成從1--—2——-3——…的一個“W”型樓梯。蜜蜂只能爬向右側相鄰的蜂房,不能反向爬行。可以等效地看成蜜蜂每次上樓梯可以走一級,也可以走兩級。
易得遞推公式 : f[n]=f[n-1]+f[n-2] (n>2) f[1]=1 f[2]=2。
#include <stdio.h>
int main()
{
int n,a,b,i;
__int64 f[51]={0,1,2};
for (i=3;i<=50;i++)
f[i]=f[i-1]+f[i-2];
scanf("%d",&n);
while (n--)
{
scanf("%d%d",&a,&b);
printf("%I64d\n",f[b-a]);
}
return 0;
}
HDU 2045 不容易系列之(3)—— LELE的RPG難題
設滿足要求的n個方格的塗色方法數爲F(n)。
因爲RPG有三種顏色,可以先枚舉出當方格數爲1、2、3時的塗法種數。
顯然,F(1)=3 (即R、P、G三種)
F(2)=6 (即RP、RG、PR、PG、GR、GP六種)
F(3)=6 (即RPG、RGP、PRG、PGR、GRP、GPR六種)
當方格的個數大於3時,n個方格的塗色方案可以由n-1方格的塗色方案追加最後一個方格的塗色方案得出,分兩種情況:
(1)對於已按要求塗好顏色的n-1個方格,在F(n-1)種合法的塗色方案後追加一個方格(第n個方格),由於合法方案的首尾顏色不同(即第n-1個方格的顏色不與第1個方格的相同),這樣,第n個方格的顏色也是確定的,它必定是原n-1個方格的首尾兩種顏色之外的一種,因此,在這種情況下的塗色方法數爲F(n-1)。
(2)對於已按要求塗好顏色的n-2個方格,可以在第n-1個方格中塗與第1個方格相同的顏色,此時由於首尾顏色相同,這是不合法的塗色方案,但可以在第n個方格中塗上一個合法的顏色,使其成爲方格長度爲n的合法塗色方案(注意:當n等於3時,由於第1(3-2)個方格與第2(3-1)個方格顏色相同,第3個方格不論怎樣塗都不會合法,因此遞推的前提是n大於3),在第n個方格中可以塗上兩種顏色(即首格外的兩種顏色,因爲與它相連的第n-1個方格和第1個方格的顏色是一樣的),因此,在這種情況下的塗色方法數爲2*F(n-2)。
由此,可得遞推公式:F(n)= F(n-1) + 2*F(n-2) (n>=4)
#include <stdio.h>
int main()
{
int i,n;
__int64 f[51];
f[0]=0;
f[1]=3;
f[2]=6;
f[3]=6;
for(i=4;i<51;i++)
f[i]=f[i-1]+2*f[i-2];
while (scanf("%d",&n)!=EOF)
{
printf("%I64d\n",f[n]);
}
return 0;
}
HDU 2046 骨牌鋪方格
設f[n]表示在2×n的一個長方形方格中用一個1× 2的骨牌鋪滿方格的方案數。顯然
2×n的長方形方格可以看成由2×(n-1)的長方形(方案數爲f[n-1])加1塊豎放的骨牌構成,也可以看成由2×(n-2)的長方形(方案數爲f[n-2])加2塊橫放的骨牌構成。
易得 遞推式爲: f[n]=f[n-1]+f[n-2] (n>2)。f[1]=1,f[2]=2。
#include <stdio.h>
int main()
{
int n,i;
__int64 f[51]={0,1,2};
for (i=3;i<=50;i++)
f[i]=f[i-1]+f[i-2];
while (scanf("%d",&n)!=EOF)
{
printf("%I64d\n",f[n]);
}
return 0;
}
HDU 2047 阿牛的EOF牛肉串
定義二維數組f[40][3],其中f[i][0]表示長度爲i,最後字符爲'E'的串的數目;
f[i][1]表示長度爲i,最後字符爲'O'的串的數目;f[i][2]表示長度爲i,最後字符爲'F'的串的數目。
顯然,對於長度爲i+1的字符串,若最後字符取'E'或'F',則其前面的一個字符任意,
即 f[i+1][0]=f[i][0]+f[i][1]+f[i][2]
f[i+1][2]=f[i][0]+f[i][1]+f[i][2]
若最後字符取'O',則其前面的字符只能爲'E'或'F',所以
f[i+1][1]=f[i][0]+f[i][2]
#include <stdio.h>
int main()
{
int n,i;
__int64 f[41][3];
f[1][0]=1;
f[1][1]=1;
f[1][2]=1;
for (i=2;i<40;i++)
{
f[i][0]=f[i-1][0]+f[i-1][1]+f[i-1][2];
f[i][2]=f[i-1][0]+f[i-1][1]+f[i-1][2];
f[i][1]=f[i-1][0]+f[i-1][2];
}
while (scanf("%d",&n)!=EOF)
{
printf("%I64d\n",f[n][0]+f[n][1]+f[n][2]);
}
return 0;
}
HDU 2048 神、上帝以及老天爺
用遞推的方法推導錯排公式。
設n個人抽n張紙條,紙條上的名字與自己的名字全不對應的方法數用F(n)表示,那麼F(n-1)就表示n-1個人抽n-1張紙條,紙條上的名字與自己的名字全不對應的方法。
n張全部不對應的紙條可以看成前n - 1張紙條再加1張紙條後,將最後1張紙條弄錯,弄錯的方式自然是與之前的紙條進行交換,交換的方式有兩種:
(1)在前n-1個全部不對應的紙條中取任意一張進行交換。n-1張紙條全部不對應的方法數爲F(n-1),在n-1張紙條中任取一張的方法數爲n-1,因此,這種情況下,方法數共有F(n-1)* (n-1)種。
(2)在前n-1張紙條中,有n-2個全不對應,有1張正確,取正確的一張進行交換。n-1張紙條中只有一張對應正確的方法數有n-1,其餘n-2張紙條全不對應的方法數有F(n-2), 因此,這種情況下,方法數共有F(n-1)* (n-1)種。
由此,可得錯排的遞推公式: F(n)=[F(n-2)+F(n-1)]*(n-1) 。
初始情況爲:F(1)=0 (只有1張紙條不可抽錯)
F(2)=1 (兩張紙條全不對應只有1種情況,即正確的兩張交換)
#include <stdio.h>
int main()
{
int i,c,n;
__int64 f[21]={0,0,1};
double ans;
for (i=3;i<=20;i++)
{
f[i]=(f[i-1]+f[i-2])*(i-1);
}
scanf("%d",&c);
while (c--)
{
scanf("%d",&n);
ans=1.0*f[n];
for (i=2;i<=n;i++)
ans/=i;
printf("%.2lf%%\n",100*ans);
}
return 0;
}
HDU 2049 不容易系列之(4)——考新郎
先求出m(1<=m<=20)個元素的錯排數,用一維數組a來保存,其中a[i]保存i個元素的錯排數。
再求在n個元素中挑選出m個元素的組合數c(n,m)。
這樣,n對新婚夫婦中m個新郎找錯了新娘的情況一共有c(n,m)*a[m]種。
#include <stdio.h>
int main()
{
int t,n,m,p,i;
__int64 c,sum,a[21]={0,0,1};
for(i=3;i<21;i++)
{
a[i]=(a[i-1]+a[i-2])*(i-1);
}
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&m);
c=1;
if (n-m>m) p=n-m;
else p=m;
for (i=n; i>p;i--)
c=c*i;
for (i=1;i<=n-p;i++)
c=c/i;
sum=c*a[m];
printf("%I64d\n",sum);
}
return 0;
}
HDU 2050 折線分割平面
設n-1條折線把空間劃分的區域數爲f(n-1)。
現有n條折線,爲了讓增加的區域更多,新增的折線要和之前的n-1條折線的2*(n-1)條邊都相交,產生4*(n-1)條新的線段和2條射線,每條線段或射線產生一個新區域,但是折線相交的頭部的兩線段一共只能產生一個區域,所以新增區域的數量爲4*(n-1) -1+2, 即 4*(n-1) +1。
所以有遞推公式:
f(n)=f(n-1)+4(n-1) + 1;
=f(n-2)+4(n-2)+4(n-1)+2;
.......
=f(n-(n-1)) +4(n-(n-1))+4(n-(n-2))+......+4(n-1) + n-1;
=f(1) +4(1+2+3+4+....+n-1)+n-1;
=2+4((n-1)(n-1+1)/2)+n-1;
=2n^2-n+1;
#include <stdio.h>
int main()
{
int c;
__int64 n;
scanf("%d",&c);
while (c--)
{
scanf("%I64d",&n);
printf("%I64d\n",2*n*n-n+1);
}
return 0;
}
原文出處:https://www.cnblogs.com/cs-whut/p/11552580.html