http://poj.org/problem?id=1953
题目大意:给定一个正整数n,确定该长度的不同吟唱模式的数量,即确定不包含相邻1的n位序列的数目。例如,对于n = 3,答案是5 (序列000,001,010,100,101是可以接受的,而011,110,111不是)。输入第一行包含场景的数量。对于每个场景,在一行中,您将得到一个小于45的正整数。每个场景的输出从包含“Scenario #i:”的一行开始,其中i是从1开始的场景的数量。然后打印一行包含没有相邻1的n位序列的序列。用空行终止该场景的输出。
也就是说,给出一个数n,那么n位二进制数有2的n次方种不同的取值,我们要找出1不相邻的种数。当n=1时可取(0,1),f[1]=1,g[1]=1,fib[1]= f[1]+ g[1]=2,当n=2时可取(00,01,10),可见是在n=1的基础上在以0结尾的取值后面加0或1,在以1结尾的取值后面加0,f[2]=f[1]+g[1]=2,g[2]=f[1]=1,fib[2]=3
算法思想:递归算法,这里我们使用一次性计算的迭代法,改进算法的效率。设f[i]表示n=i时以0结尾的取值数,g[i]表示n=i时以1结尾的取值数,fib[i]表示n=i时的取值数。以0结尾可以在后面加0或1,以1结尾可以在后面加0,可以得到递归方程:
1) f[i]=g[i-1]+f[i-1]; i>1
2) g[i]=f[i-1]; i>1
3) fib[i]=f[i]+g[i]; i>0
4) f[1]=1; i=1
5) g[1]=1; i=1
观察递归方程可以发现,这是一个斐波那契数列,(2,3,5,8,13…)
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int fib[46];// 没有相邻的1的n位序列的序列数 6 int f[46],g[46]; 7 f[1]=1; 8 g[1]=1; 9 fib[1]=f[1]+g[1]; 10 for(int i=2;i<=45;i++) 11 { 12 f[i]=f[i-1]+g[i-1]; 13 g[i]=f[i-1]; 14 fib[i]=f[i]+g[i]; 15 } 16 cin>>fib[0];//案例数 17 for(int i=1;i<=fib[0];i++) 18 { 19 int temp; 20 cin>>temp; 21 cout<<"Scenario #"<<i<<":\n"<<fib[temp]<<endl<<endl; 22 } 23 return 0; 24 }