Codeforces-738C

題目簡介

這道題給我們n兩汽車,每輛汽車有所需要的價錢c與其油箱的最大存油量v,然后給我們一段路程s,其中有k個加油站,問是否能在t時間內跑完這段路程。所有汽車均有兩種運行模式:
1.普通模式:1km 用 2min 用 1L 油。
2.加速模式:1km 用 1min 用 2L 油。
如果能跑完則輸出最少需要花費的租車費。
如果全都沒辦法跑完全程則輸出-1。
(二分+貪心)

樣例輸入

3 1 8 10
10 8
5 7
11 9
3

樣例輸出

10

解題思路

1.用結構體儲存汽車數據,并將汽車數據按照油箱大小從小到大排序。
2.計算每段加油站之間的距離。(ps : 加油站的位置不一定是順序給出的 , 需要排序)
3.首先判斷油箱最大的汽車是否能在規定時間內跑到終點,若不能直接輸出-1。
4.若油箱最大的汽車能跑完全程則用二分法找出能跑完全程的最小油箱量。然后再在最小油箱量和最大油箱的汽車數據之間選出需要花費錢最小的那一個。

關于如何判斷是否滿足條件:
本題只有三種情況。(按照每一段距離來計算時間,記油箱容量為x,若時間小于規定時間則成立)
1.distance > x ,則中途沒油。
2.distance * 2 <= x , time += distance 。在這段距離內能全速跑。
3.distance < x < distance2 , time += (3distance - x) 。 盡量加速跑。

數據較大,最好用long long。
(ps : 因為我比較菜所以幾乎所有東西都改成了long long )

代碼如下

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn = 200050;

LL con = 0;      // 計算有多少段距離;
LL sta[maxn];     // 開一個加油站位置的數組;
LL dis[maxn];     // 每兩個加油站之間距離的數組;
LL  n,k,s,t;      // n代表汽車數量,k代表加油站數量,s為路程,t為最大時間;
struct car
{
    LL c,v;      // 包含車子的數據,c為價錢,v為最大油量;
} cars[maxn];

bool cmp(car a,car b)       // 讓車子數據按照油量從小到大進行排序;
{
    if(a.v != b.v) return a.v < b.v;
}

bool judge(LL x)
{
    LL time = 0;

    for(int i = 0 ; i < con ; i++)
    {
        if(dis[i] > x) return false ;// 若距長于最大油量則不可能通過;
        if(2*dis[i] <= x) time += dis[i];
        else time += (3*dis[i] - x);
    }
    if(time > t) return false;
    return true;
}

int main()
{
    scanf("%lld%lld%lld%lld",&n,&k,&s,&t);
    for(int i = 1 ; i <= n ; i++)                // 從1到n讀取汽車的數據;
        scanf("%lld%lld",&cars[i].c,&cars[i].v);
    sta[0]=0;
    for(int i = 1 ; i <= k ; i++)          // 從1到n讀取加油站的位置;
        scanf("%lld",&sta[i]);
    sta[k+1]=s;
    sort(sta,sta+k+1);  // 將加油站的位置按從小到大排序;
    for(int i = 1 ; i <= k+1 ; i++)   // 儲存每段距離;
    {
        dis[con]=sta[i]-sta[i-1];
        con++;
    }
    sort(cars+1,cars+1+n,cmp);  // 講1到n號車按油量從小到大排序;
    if(!judge(cars[n].v)) printf("-1\n");  //若最大油量不可能跑到終點則輸出-1;
    else                                 // 二分查找滿足條件的最小油量;
    {
        LL l = 1;
        LL r = n;
        LL goal = n;
        while(l <= r)
        {
            LL mid = (l + r)/2;
            if(judge(cars[mid].v))
            {
                r = mid - 1;
                goal = mid;
            }
            else l = mid + 1;
        }

        LL minn = 1000000005;
        for(int i = goal ; i <= n ; i++)
        {
            if(cars[i].c <= minn) minn = cars[i].c;
        }
        printf("%lld\n",minn);
    }

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經驗。 張土汪:刷leetcod...
    土汪閱讀 12,769評論 0 33
  • 貪心算法 貪心算法總是作出在當前看來最好的選擇。也就是說貪心算法并不從整體最優考慮,它所作出的選擇只是在某種意義上...
    fredal閱讀 9,279評論 3 52
  • 〇、引言 大家好,我是無涯,來自廣西柳州,目前在北京就職于一家亞洲最大的上市汽車租賃公司,從事營銷廣告工作,其實呢...
    I無涯閱讀 1,229評論 0 49
  • 我叫木村翔,我是一名拳擊手。 01 雖然我是職業的拳擊手,可是拳擊并不能給我帶來一份體面的收入,甚至不能保障我基本...
    六一說閱讀 338評論 1 1
  • 1 2017年9月3日小犟龜班進入了開學時期。 2我完成的假期所有的作業,還進行了一項特殊的比賽,鋼琴比賽。 3這...
    張忠楷閱讀 166評論 0 1