传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1297

Children’s Queue

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16830    Accepted Submission(s): 5643

Problem Description

There are many students in PHT School. One day, the headmaster whose name is PigHeader wanted all students stand in a line. He prescribed that girl can not be in single. In other words, either no girl in the queue or more than one girl stands side by side. The case n=4 (n is the number of children) is like
FFFF, FFFM, MFFF, FFMM, MFFM, MMFF, MMMM
Here F stands for a girl and M stands for a boy. The total number of queue satisfied the headmaster’s needs is 7. Can you make a program to find the total number of queue with n children?

Input

There are multiple cases in this problem and ended by the EOF. In each case, there is only one integer n means the number of children (1<=n<=1000) 

Output

For each test case, there is only one integer means the number of queue satisfied the headmaster’s needs.

Sample Input

1 2 3

Sample Output

1 2 4

题目解释:

有n个位置,男孩女孩排队,要求有女孩的话,至少要2个女孩在一起。 

解题思路:

1)如果最后一个是男孩,前面n-1是合法队列,则方法数为f(n-1),如果前面n-1个不是合法队列,则这n个也不可能是合法队列

2)如果最后一个是女孩,那么第n-1个必定是女孩

   <1>如果前n-2个是合法队列,方法数为f(n-2)

   <2>如果前n-2个不是合法队列,那满足条件的队列应该是f(n-4)+男+女,方法数为f(n-4)

所以f(n)=f(n-1)+f(n-2)+f(n-4)

注意:n的值最大是1000,结果非常庞大,要用到大数加法的思想,可以压1位存或者压4位存,压4位存的时候要注意当过程中的“余数”不足4位的时候要前面补0.

看下最大的结果,别怕哈哈哈:12748494904808148294446671041721884239818005733501580815621713101333980596197474744336199742452912998225235910891798221541303838395943300189729514282623665199754795574309980870253213466656184865681666106508878970120168283707307150239748782319037

ac代码:

压4位存

#include<iostream>
using namespace std;
int main()
{
    int arr[1001][101]={0};
    arr[0][1]=1;
    arr[1][1]=1;
    arr[2][1]=2;
    arr[3][1]=4;
    for(int i=4;i<1001;i++)
    {
        for(int j=1;j<101;j++)
        {
            arr[i][j]+=arr[i-1][j]+arr[i-2][j]+arr[i-4][j];//
            arr[i][j+1]=arr[i][j]/10000;//更新商
            arr[i][j]=arr[i][j]%10000;//更新余数
        }
    }
    int num;
    while(cin>>num)
    {
        int k=100;
        for(;arr[num][k]==0;k--);//找到待输出的商
        cout<<arr[num][k];
        for(;k>1;)
        {
            k--;
            cout.width(4);
            cout.fill('0');
            cout<<arr[num][k];
        }
        cout<<endl;
    }
}

压1位存

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long s[1010][1005];
int main()
{
    int i,j,n;
    memset(s,0,sizeof(s));
    s[1][0]=1;s[2][0]=2;s[3][0]=4;s[4][0]=7;
    for(i=5;i<=1000;i++){
        for(j=0;j<=1000;j++)
            s[i][j]=s[i-1][j]+s[i-2][j]+s[i-4][j];
        for(j=0;j<=1000;j++){
            if(s[i][j]>=10){
                s[i][j+1]+=s[i][j]/10;
                s[i][j]%=10;
            }
       }
    }
    
    while(cin>>n){
        i=1000;
        while(i--){
            if(s[n][i]!=0)
                break;
        }
        cout<<s[n][i];
        i--;
        for(;i>=0;i--)
            printf("%d",s[n][i]);
        cout<<endl;
    }
    return 0;
}