HDU - 1201 - 18歲生日 - [局部分離思想]

HDU - 1201 - 18歲生日

https://vjudge.net/problem/HD...ios

一句話題意:給定出生日期(格式爲1988-03-07),求到18歲生日爲止經歷了多少天;沒有18歲生日輸出-1。算法

這個題目太普通了,相似的問題可能滿大街都是。這不是一個算法競賽等級的題目,可是仍是有的好說。我要記錄的是我作這題的思考方式。函數

解:spa

首先考慮閏年。通常來講,公元閏年的肯定方法以下:年份若爲400的正整倍數時,閏;不然,年份是4的正整倍數且不是100的正整倍數時,閏;都不符合,平。這點體如今函數is_leap裏。.net

我發現,若今年是閏年,日期在2月29日以前或以後的兩種情形到「明年今日」的天數是不一樣的。如2008-03-012009-03-01經歷366天,2008-02-282009-02-28經歷365天。code

對稱地,若今年是平年,明年是閏年也有相似的規律可說。ci

這就是我要記錄的「局部分離思想」。這個問題一開始看很複雜,可是咱們發現,這一年到下一年,無非只有3種大情形。日期在2月29日以前簡記爲「前」;日期在這以後(含)簡記爲「後」。列表以下。get

  1. 平=>平 前365天;後365天string

  2. 平=>閏 前365天;後366天it

  3. 閏=>平 前366天;後365天

這樣一來,問題就迎刃而解了。

代碼以下。

//AC,0ms;
#ifdef LOCAL
    #include<ctime>
#endif
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<sstream>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#define LL long long
using namespace std;
int is_leap(int a){
    if(a%100 == 0) return !(a%400);
    else return !(a%4);
}
int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
    clock_t start, end;
    start = clock();
#endif
    int t;
    cin >> t;
    string s;
    while(t--){
        int y,m,d,modify=0,after=1;
        cin >> y >> m >> d;
        m=-m;
        d=-d;
        if(m == 2 && d == 29){
            cout << -1 << endl;
            continue;
        }else if(m<=2 && d<=28) after = 0;
        for(int i = y;i<=y+17;i++){
            if(is_leap(i)){
                if(!after){
                    modify++;
                }
            }else{
                if(is_leap(i+1)){
                    if(after){
                        modify++;
                    }
                }
            }
        }
        cout << modify + 365*18 << endl;
    }
#ifdef LOCAL
    end = clock();
    cout << "*************************" << endl;
    cout<< "Computing time: "<<(double)(end - start)*1000 / CLOCKS_PER_SEC<<"ms"<<endl;
#endif
    return 0;
}

我這裏採用了增量的形式,在18*365天的基礎上加上多出來的那幾天。爲啥只取到y+17呢?由於咱們只用考慮這一年變到下一年的情形。第18年不會再變到下一年,因此只計算到y+17爲止。

相關文章
相關標籤/搜索