SJTUOJ 1008. 二哥买期货

问题内容

Description
二哥想知道在一段时期内,一共有多少个交易日。期货交易日的限定如下:

周六、周日不能交易
元旦期间(1月1日)不能交易
五一劳动节期间(5月1日至3日)不能交易
十一国庆节期间(10月1日至7日)不能交易
没有在上述要求中提到的日期均可交易
Input Format
第一行有一个整数n,表示一共有n组数据。

每组数据都有一行,是两个用空格分开的日期,分别为开始日期和结束日期。日期格式为YYYY-MM-DD(比如2010-11-11);数据保证开始日期不晚于结束日期。

对于所有数据:n≤365n≤365
对于30%的数据:日期范围从2010-11-23至2012-12-21

对于70%的数据:日期范围从1900-01-01至9999-12-31

Output Format
输出共n行,每行一个整数,对应于一组数据。

每组数据需要输出在指定日期区间内,共有多少个交易日;区间的开始和结束日期也算在内(如果是交易日的话)。

Sample Input
4
2010-11-18 2010-11-20
2010-01-01 2010-01-01
2010-05-01 2010-05-03
2010-10-01 2010-10-07
Sample Output
2
0
0
0

代码实现及分析

思路一:将每年按节日划分为三段XXXX-01-01至XXXX-04-30,XXXX-05-01至XXXX-09-01,XXXX-10-01至XXXX-12-31分别计算天数,再对起始日期进行判断,如果是交易日就加回来。

#include <stdio.h> 
#include <string.h>
 
int dayos[8099];
 
int get_doy(int yyyy,int mm,int dd)
{
    int isLeap = (!(yyyy % 4) && (yyyy % 100)) || !(yyyy % 400);
    int doy = 0,moy;
    int mds[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    for(moy = 0; moy < mm - 1; moy++){
        doy += mds[moy]+((1==moy&&isLeap)?1:0);
    }
    doy += dd;
    return doy;
}
 
int judge(int dayo, int emm, int edd, int toy){
    if( 1 == emm && 1 == edd ){
        return 0;
    }
    if( 5 == emm && 1 <= edd && 3 >= edd){
        return 0;
    }
    if( 10 == emm && 1 <= edd && 7 >= edd){
        return 0;
    }
    
    if((dayo+toy-1) % 7 > 4){
        return 0;
    }
    return 1;
}
int main() 
{
    int n;
    int syyyy,smm,sdd,eyyyy,emm,edd;
    int tyyyy;
    int foy,toy,soy,eoy;
    int isLeap = 0, dayo = 0;
    
    int daycnt = 0,i,tempcnt,daystart,leftdays,alldays;
    int semap[3][4]={{1,1,4,30},{5,3,9,30},{10,7,12,31}};
    dayos[0] = 0;
    for(i = 0;i < 8099;i++){
        isLeap = (!((i+1900) % 4) && ((i+1900) % 100)) || !((i+1900) % 400);
        dayos[i+1] = (dayos[i] + (isLeap?366:365))%7;
    }
    scanf("%d", &n);
    while(n--){
        scanf("%d-%d-%d %d-%d-%d",&syyyy,&smm,&sdd,&eyyyy,&emm,&edd);
        daycnt = 0;
        foy = get_doy(syyyy,smm,sdd);
        toy = get_doy(eyyyy,emm,edd);
        for(tyyyy=syyyy;tyyyy <= eyyyy;tyyyy++){
            dayo=dayos[tyyyy-1900];
            for(i = 0; i < 3; i++){
                soy = get_doy(tyyyy,semap[i][0],semap[i][1]);
                eoy = get_doy(tyyyy,semap[i][2],semap[i][3]);
                if(tyyyy == syyyy) 
                {
                    if(foy > eoy){
                        continue;
                    }
                    else if(foy > soy && foy <= eoy)
                    {
                        soy = foy;
                    }
                }
                if(tyyyy == eyyyy)
                {
                    if(toy < soy){
                        continue;
                    }
                    else if(toy >= soy && toy < eoy){
                        eoy = toy;
                    }
                }
                tempcnt = eoy - soy;
                daystart = (dayo + soy)%7;
                alldays = daystart + tempcnt;
                leftdays = alldays % 7;
                tempcnt = (alldays / 7) * 5 - (daystart > 4 ? 5:daystart) + (leftdays > 4 ? 5:leftdays);
                daycnt += tempcnt;
            }
        }
        //Judge if toy is weekday
        daycnt += judge(dayos[syyyy-1900],smm,sdd,foy);
 
        printf("%d\n",daycnt);
    }
    return 0;
}

这种方法分段内容太多所以效率较低:时间531ms 空间:9344kb

思路二:整段计算前后天数再将所有节日判断后剔除。

// 暂略

猜你喜欢

转载自blog.csdn.net/Phoenix5443/article/details/85037656