zoukankan      html  css  js  c++  java
  • 【高精度递推】【HDU1297】Children’s Queue



    Children’s Queue

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


    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
     

    Author
    SmallBeer (CML)
     

    Source
     

    题目大意就是:
    长度为N的序列 F要么不出现 要么不单独出现 即MFM FMM FMF 的情况

    一开始的时候想的是排列组合的方法
    N个中有k个M,然后再将N-k个F拆开 插入 k+1个空格内的方案数。
    不用想 这样的复杂度十分的高 先不谈时间复杂度
    空间复杂度也得爆 要开C[1000][1000][70];

    所以考虑递推
    设A[i] 表示长度为i时的方案数
        F[i] 表示末尾为F 且除去末尾的一串F后满足题目条件的方案数(即F,MF,MMFF也满足条件。除去末尾的一串F后为空,M,MM)
        M[i]表示末尾为M满足条件的方案数
       
        递推方程
        A[i]=A[i-1]+F[i-1] 
        F[i]=M[i-1]+F[i-1]
        M[i]=A[i-1];

     要写高精度

    #include <cstdio>  
    #include <cstdlib>  
    #include <cmath>  
    #include <cstring>  
    #include <ctime>  
    #include <algorithm>  
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    #define B 10000   
    using namespace std;
    struct Bigint 
    {
        int operator[](int index) const {  
            return digit[index];  
        }  
      
        int& operator[](int index) {  
            return digit[index];  
        }  
    	int len;
    	int digit[100];
    };
    Bigint A[1001],F[1001],M[1001];
    void highadd(Bigint &c,Bigint &a,Bigint &b)
    {
    	c.len=max(a.len,b.len)+1;
    	int temp=0;
    	for(int i=0;i<c.len;i++)
    	{
    		temp+=a[i]+b[i];
    		c[i]=temp%B;
    		temp=temp/B;
    	}
    	if(c[c.len-1]==0) c.len--;
    }
    void YCL()
    {
    	A[1].len=1,A[1][0]=1;F[1].len=1;F[1][0]=1;M[1].len=1,M[1][0]=1;
    	for(int i=2;i<=1000;i++)
    	{
    		highadd(A[i],A[i-1],F[i-1]);
    		highadd(F[i],M[i-1],F[i-1]);
    		M[i]=A[i-1];
    	}
    }
    void output(int n)
    {
    	printf("%d",A[n][A[n].len-1]);
    	for(int i=A[n].len-2;i>=0;i--)
    	printf("%04d",A[n][i]);
    	printf("
    ");
    }
    int main()
    {
    	int n;
    	YCL();
    	while(cin>>n)
    	{
    		output(n);
    	}
    }
      



    另外一种递推思路:

    思路如下:

    一个长度n的队列可以看成一个n - 1的队列再追加的1个小孩,这个小孩只可能是:

    a.男孩,任何n - 1的合法队列追加1个男孩必然是合法的,情况数为f[n - 1];

    b.女孩,在前n - 1的以女孩为末尾的队列后追加1位女孩也是合法的,我们可以转化为n - 2的队列中追加2位女孩;

    一种情况是在n - 2的合法队列中追加2位女孩,情况数为f[n - 2];

    但我们注意到本题的难点,可能前n - 2位以女孩为末尾的不合法队列(即单纯以1位女孩结尾),也可以追加2位女孩成为合法队列,而这种n - 2不合法队列必然是由n - 4合法队列+1男孩+1女孩的结构,即情况数为f[n - 4]。


     
  • 相关阅读:
    Linux命令应用大词典-第11章 Shell编程
    Kubernetes 学习12 kubernetes 存储卷
    linux dd命令
    Kubernetes 学习11 kubernetes ingress及ingress controller
    Kubernetes 学习10 Service资源
    Kubernetes 学习9 Pod控制器
    Kubernetes 学习8 Pod控制器
    Kubernetes 学习7 Pod控制器应用进阶2
    Kubernetes 学习6 Pod控制器应用进阶
    Kubernetes 学习5 kubernetes资源清单定义入门
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480421.html
Copyright © 2011-2022 走看看