1. 程式人生 > >計蒜客題目 法師康的工人

計蒜客題目 法師康的工人

三個法師康的工人每天早上6點到工廠開始到三條產品生產線上組裝桔子手機。第一個工人在200時刻開始(從6點開始計時,以秒作為單位)在生產線上開始生產,一直到1000時刻。第二個工人,在700時刻開始,在1100時刻結束。第三個工人從1500時刻工作到2100時刻。期間最長至少有一個工人在生產線上工作的連續時間為900秒(從200時刻到1100時刻),而最長的無人生產的連續時間(從生產開始到生產結束)為400時刻(1100時刻到1500時刻)。

你的任務是用一個程式衡量N個工人在N條產品線上的工作時間列表(1≤N≤5000,以秒為單位)。

·最長的至少有一個工人在工作的時間段

·最長的無人工作的時間段(從有人工作開始計)

輸入第1行為一個整數N,第2-N+1行每行包括兩個均小於1000000的非負整數資料,表示其中一個工人的生產開始時間與結束時間。輸出為一行,用空格分隔開兩個我們所求的數。

樣例輸入

3
200 1000
700 1100
1500 2100

樣例輸出

900 400
#include<stdio.h>
#include<algorithm>

using namespace std;

struct worker{
    int stime;
    int etime;
    bool operator < (const worker &x) const{//過載運算子,使排序時,stime小的靠前,stime相同時etime小的靠前
        if(stime!=x.stime) return stime<x.stime;
        else return etime<x.etime;
    }
}buf[5000];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++) scanf("%d%d",&buf[i].stime,&buf[i].etime);
    if(n==1){//對於只有1個人的特殊處理
        printf("%d 0",buf[0].etime-buf[0].stime);
        return 0;
    }
    sort(buf,buf+n);
    worker pre=buf[0], p=buf[1];
    int wtime=buf[0].etime-buf[0].stime, ntime=0, end=buf[0].etime;
    int flag=0;
    for(int i=1;i<n;){
        if(end>=p.stime){//若結束時間大於下一個的開始時間(無間斷)
            end=end>p.etime?end:p.etime;
        }
        else{//結束時間小於下一個的開始時間(有間斷)
            wtime=wtime>(end-pre.stime)?wtime:(end-pre.stime);
            ntime=ntime>(p.stime-end)?ntime:(p.stime-end);
            end=p.etime;
            pre=p;
        }
        i++;
        p=buf[i];
    }
    printf("%d %d",wtime,ntime);
    
    return 0;
}

思路:對工作時間進行排序,若工作時間之間沒有間斷,則不斷更新目前的結束時間end,若工作時間之間有間斷,則計算最大工作時間,最大空閒時間,並更新end。以此迴圈整個工作時間列表。在程式碼中,用pre和p代表前一個工作時間和當前的工作時間,用end記錄目前的結束時間。遍歷時判斷:end是否大於等於p的結束時間?若是,則更新end(取目前end與p結束時間之間的較大值),若不是,則計算工作時間wtime與ntime,同時更新end

總結:思考很重要,同時注意結束時間與開始時間相等時,也是可以無縫接上的。