题目链接: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): 11119 Accepted Submission(s): 3578
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?
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递推问题实现起来很简单,但得到递推公式确实很麻烦,就像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).n很大,必须用高精度处理。先来个C++版的吧,压位+打表,够快了吧。#include<stdio.h> #define carry 100000000 const int maxn=1005; int a[maxn][maxn]={0}; //每个元素可以存储8位数字,所以2005位可以用260个数组元素存储。 int main() { int i,j,n; a[1][0]=1; a[2][0]=2; a[3][0]=4;a[4][0]=7; for(i=5;i<maxn;i++) { for(j=0;j<maxn;j++) a[i][j]+=a[i-1][j]+a[i-2][j]+a[i-4][j]; for(j=0;j<maxn;j++) //每八位考虑进位。 if(a[i][j]>carry) { a[i][j+1]+=a[i][j]/carry; a[i][j]=a[i][j]%carry; } } while(scanf("%d",&n)!=EOF) { for(j=maxn-1;j>=0;j--) if(a[n][j]!=0) break; //不输出高位的0 printf("%d",a[n][j]); for(j=j-1;j>=0;j--) printf("%08d",a[n][j]); //每个元素存储了八位数字,所以控制输出位数为8,左边补0 printf("\n"); } return 0; }
下面是AC了的JAVA代码import java.io.*; import java.util.*; import java.math.*; public class Main { public static void main(String args[]){ Scanner cin=new Scanner(new BufferedInputStream(System.in)); BigInteger a[]=new BigInteger[1005]; int n; while(cin.hasNext()) { a[0]=BigInteger.valueOf(1); a[1]=BigInteger.valueOf(1); a[2]=BigInteger.valueOf(2); a[3]=BigInteger.valueOf(4); n=cin.nextInt(); if(n<4){ System.out.println(a[n]); } else { for(int i=4;i<=n;i++){ a[i]=a[i-1].add(a[i-2]).add(a[i-4]); } System.out.println(a[n]); } } } }