【noi 2.6_9265】取数游戏(DP)
题意:从自然数1到N中不取相邻2数地取走任意个数,问方案数。
解法:f[i][1]表示在前i个数中选了第i个的方案数,f[i][0]表示没有选第i个。f[i][1]=f[i-1][0]; f[i][0]=f[i-1][1]+f[i-1][0]
而若简化方程式,用f[i]表示从前i个中取数的方案数。便是f[i]=f[i-2]+f[i-1],斐波拉契的递推式。
推导过程如下:
若用x,y,f[i-2]表示f[i-2][1],f[i-2][1],f[i-2][1]+f[i-2][0],xx,yy,f[i-1]表示f[i-1][]的,xxx,yyy,f[i]表示f[i][]的:
f[i-2]=x+y;
xx=y; yy=x+y; f[i-1]=x+2*y;
xxx=yy=x+y; yyy=xx+yy=x+2*y; f[i]=2*x+3*y=f[i-2]+f[i-1]
以上就可以理性逻辑推导出来f[i]=f[i-2]+f[i-1]。
而在稍微感性一点的理解上,我是这样想的:
对于f[i],不取a[i]则对a[i-1]随意(可取可不取),便为f[i-1]的方案数;
取a[i]则不能取a[i-1],不是f[i-1],而对于a[i-2]随意(可取可不取),便为f[i-2]的方案数。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 using namespace std; 5 6 long long f[55]; 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 f[1]=2,f[2]=3; 12 for (int i=3;i<=n;i++) 13 f[i]=f[i-2]+f[i-1]; 14 printf("%lld\n",f[n]); 15 return 0; 16 }
注意——斐波拉契数列第50项已经超了int范围,用long long输出要用%lld。