1. 程式人生 > >SJTUOJ 1008. 二哥買期貨

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

思路二:整段計算前後天數再將所有節日判斷後剔除。

// 暫略