首页 > 代码库 > hdu1297Children’s Queue

hdu1297Children’s Queue

 

递推问题实现起来很简单,但得到递推公式确实很麻烦,就像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");
 }
}

hdu1297Children’s Queue