递推问题实现起来很简单,但得到递推公式确实很麻烦,就像DP一样。
分析(部分出自HDU的PPT):
设:F(n)表示n个人的合法队列,则:
按照最后一个人的性别分析,他要么是男,要么是女,所以可以分两大类讨论:
1、如果n个人的合法队列的最后一个人是男,则对前面n-1个人的队列没有任何限制,他只要站在最后即可,所以,这种情况一共有F(n-1);
2、如果n个人的合法队列的最后一个人是女,则要求队列的第n-1个人务必也是女生,这就是说,限定了最后两个人必须都是女生,这又可以分两种情况:
(1)、如果队列的前n-2个人是合法的队列,则显然后面再加两个女生,也一定是合法的,这种情况有F(n-2);
(2)难点在于,即使前面n-2个人不是合法的队列,加上两个女生也有可能是合法的,当然,这种长度为n-2的不合法队列,不合法的地方必须是尾巴,就是说,这里说的长度是n-2的不合法串的形式必须是“F(n-4)+男+女”,这种情况一共有F(n-4).
所以递推公式为F(n)=F(n-1)+F(n-2)+F(n-4).
另外需要注意的是 这个递推式的数据范围到了1000,int甚至long long 都已经无法承载最大边界。
百度到了一个用大数处理的我能看懂的代码....
#include<stdio.h>
int m[1001][246];
int main()
{
int i,j;
int temp;
int n,flag;
//f[n]=f[n-1]+f[n-2]+f[n-4] 用打表法
m[1][0]=1;
m[2][0]=2;
m[3][0]=4;
m[4][0]=7;
for(i=5;i<=1001;i++)
{
temp=0;
for(j=0;j<246;j++)
{
m[i][j]=m[i-1][j]+m[i-2][j]+m[i-4][j]+temp; //用了数组进行大数运算,由低到高倒着排
temp=0;
if(m[i][j]>9)
{
temp=m[i][j]/10;
m[i][j]=m[i][j]%10;
}
}
}
while(scanf("%d",&n)!=EOF)
{
flag=0;
for(i=245;i>=0;i--) //倒着输出
{
if(!flag&&m[n][i])
flag=1;
if(flag)
printf("%d",m[n][i]);
}
printf("\n");
}
}