• HDU1297 Children’s Queue


    问题链接HDU1297 Children’s Queue

    问题描述参见上文。

    问题分析这个问题看似一个字符串排列问题,然而只是计算排列数量,可以用类似于计算斐波拉契数列的方法来解。

    对于各种排列而言,用f(n)表示其长度为n时的可能数,有以下的情形:

    长度为1时,只有1种可能,即“M”(女生不能单独站立,下同);

    长度为2时,有2种可能,即“FF”和“MM”;

    长度为3时,有4种可能,即“FFF”、“FFM”、“MFF”和“MMM”;

    长度为4时,有7种可能,即“FFFF”、“FFFM”、“FFMM”、“MFFM”、“MFFF”、“MMFF”“MMMM”;

    长度为n>4时,对于之前长度n-1的排列,加一个M是可行的(最好是男孩的情形);对于之前长度n-2的排列,加上FF是可行的(加MM有可能造成排列重复,这是最后是女孩的情形,并且前n-2个人是可行的排列);另外一种情况是,前n-2个人是不可行的排列,即最后的两个人是“MF”,再加上两个“FF”就变成可行的排列,这种情况也就是在n-4人可行的排列基础上加上“MFFF”。

    根据以上的分析,得出递推式子:f(n)=f(n-4)+f(n-2)+f(n-1)(n>4)。

    然而,根据这个公式计算f(n),其数列值的增长速度太快了,需要构筑一个大整数类来解决。本程序给出的是简单的大整数计算类,只实现了包含了数组的并且只有+运算的无符号大整数类,解决本问题是没有问题的。

    另外需要注意的是,ACM程序的测试集往往比较大,即重复计算的数据量很大。对于本题来说,各种n都会被测试。所以不用打表的方法,计算时间上会超时。所以将各种n的排列数预先计算好放在数组中备查,是一种加快速度的方法。

    程序说明(略)。

    AC的C语言程序如下:

    /* HDU1297 Children’s Queue */
    
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    /* 无符号整数类,整数放在字符串中,可以用整数初始化。
     * 只有以下功能:
     * 1.数组
     * 2.加运算。
     */
    class UBigInt {
    private:
        string num;
    public:
        UBigInt();
        UBigInt(int n);
        void setNumber(string s);
        const string& getNumber(); // retrieves the number
        UBigInt operator + (UBigInt b);
    private:
        string add(string number1, string number2);
        UBigInt& operator [] (int n);
    };
    
    UBigInt::UBigInt() { // empty constructor initializes zero
        num = "0";
    }
    
    UBigInt::UBigInt(int n) {
        stringstream ss;
        string s;
        ss << n;
        ss >> s;
        setNumber(s);
    }
    
    void UBigInt::setNumber(string s) {
        num = s;
    }
    
    const string& UBigInt::getNumber() { // retrieves the number
        return num;
    }
    
    UBigInt UBigInt::operator + (UBigInt b) {
        UBigInt addition;
        addition.setNumber( add(getNumber(), b.getNumber() ) );
    
        return addition;
    }
    
    string UBigInt::add(string number1, string number2) {
        string add = (number1.length() > number2.length()) ?  number1 : number2;
    
        int diffLength = abs( (int) (number1.size() - number2.size()) );
        if(number1.size() > number2.size())
            number2.insert(0, diffLength, '0'); // put zeros from left
        else// if(number1.size() < number2.size())
            number1.insert(0, diffLength, '0');
    
        char carry = 0;
        for(int i=number1.size()-1; i>=0; --i) {
            add[i] = (carry+(number1[i]-'0')+(number2[i]-'0')) + '0';
    
            if(i != 0) {
                if(add[i] > '9') {
                    add[i] -= 10;
                    carry = 1;
                } else
                    carry = 0;
            }
        }
        if(add[0] > '9') {
            add[0]-= 10;
            add.insert(0,1,'1');
        }
        return add;
    }
    
    UBigInt& UBigInt::operator [] (int n) {
        return *(this + (n*sizeof(UBigInt)));
    }
    
    UBigInt t[1001];
    
    void setfib(int n)
    {
        t[1] = 1;
        t[2] = 2;
        t[3] = 4;
        t[4] = 7;
    
        for(int i=5; i<=n; i++)
            t[i] = t[i-4] + t[i-2] + t[i-1];
    }
    
    int main(void)
    {
        int n;
    
        setfib(1000);
    
        while(scanf("%d", &n) != EOF) {
            cout << t[n].getNumber() << endl;
        }
    
        return 0;
    }


  • 相关阅读:
    乐在其中设计模式(C#) 享元模式(Flyweight Pattern)
    乐在其中设计模式(C#) 抽象工厂模式(Abstract Factory Pattern)
    新瓶旧酒ASP.NET AJAX(7) 客户端脚本编程(Sys命名空间下的类)
    [翻译]在GridView中针对鼠标单击的某一独立单元格进行编辑
    乐在其中设计模式(C#) 中介者模式(Mediator Pattern)
    [翻译]使用C#创建SQL Server的存储过程(Visual Studio 2005 + SQL Server 2005)
    [翻译]ASP.NET 2.0中的健康监测系统(Health Monitoring)(1) 基本应用
    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(11)各种线程相关操作类
    Oracle如何实现创建数据库、备份数据库及数据导出导入的一条龙操作
    Winform分页控件支持表头全选操作实现
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7564816.html
Copyright © 2020-2023  润新知