題目簡介
這道題給我們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);
}
}