【解題報告】 洛谷P1542 包裹快遞
【解題報告】 洛谷P1542 包裹快遞
題目描述
小K成功地破解了密文。但是乘車到X國的時候,發現錢包被偷了,於是無奈之下只好作快遞員來攢足路費去Orz教主……
一個快遞公司要將n個包裹分別送到n個地方,並分配給郵遞員小K一個事先設定好的路線,小K需要開車按照路線給的地點順序相繼送達,且不能遺漏一個地點。小K得到每個地方可以簽收的時間段,並且也知道路線中一個地方到下一個地方的距離。若到達某一個地方的時間早於可以簽收的時間段,則必須在這個地方停留至可以簽收,但不能晚於簽收的時間段,可以認為簽收的過程是瞬間完成的。
為了節省燃料,小K希望在全部送達的情況下,車的最大速度越小越好,就找到了你給他設計一種方案,並求出車的最大速度最小是多少。
輸入格式
第1行為一個正整數n,表示需要運送包裹的地點數。
下面n行,第i+1行有3個正整數xi,yi,si,表示按路線順序給出第i個地點簽收包裹的時間段為[xi, yi],即最早為距出發時刻xi,最晚為距出發時刻yi,從前一個地點到達第i個地點距離為si,且保證路線中xi遞增。
可以認為s1為出發的地方到第1個地點的距離,且出發時刻為0。
輸出格式
僅包括一個正數,為車的最大速度最小值,結果保留兩位小數。
輸入輸出樣例
輸入 #1
3
1 2 2
6 6 2
7 8 4
輸出 #1
2.00
說明/提示
對於20%的資料,\(n \le 10\);
對於30%的資料\(x_i,y_i,x_i\le 1000\)
對於50%的資料,\(n\leq1000\)
對於100%的資料,\(n\le 200000,x_i\le y_i\le 10^8,s_i \le 10^7\)
時限1s
第一段用1的速度在時間2到達第1個地點,第二段用0.5的速度在時間6到達第2個地點,第三段用2的速度在時間8到達第3個地點。
思路
二分
看到這道題,有一個關鍵詞,最大速度最小,這樣我們就像想到了二分的方法,並且速度越大,當然可以所有都送達,所以這裡要找的是一個臨界點的問題符合單調性,所以更加確定的使用了二分的方法。
大概思路就是設定一個check函式,引數為這個最大速度的最小\(V_{min}\)然後對於時間進行模擬,如果在某個包裹要求的時間之前達到了這個包裹的地點(將原來的總時間加上路程/速度),當然就是要等到這個時間,直接把總時間\(a\)
這道題還需要注意的是double的精度只有16位(包括小數),如果整數部分過大的話將會捨棄小數部分的精度,所以我們要使用long double ,在輸出的時候要用 %Lf這個L一定要是大寫的,否則輸出的還是double精度的數字。
程式碼
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
const int MAXN=2000005;
const double eps=0.00001;
int n;
int x[MAXN],y[MAXN],s[MAXN];
long double ans;
bool check(double vmin)
{
long double a=0;//a表示已經進行的時間
for(int i=1;i<=n;i++)
{
a+=s[i]/vmin;
if(a<x[i])
a=x[i];
if(a>y[i])
return false;
}
return true;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i]>>s[i];
long double l=0,r=1e9;
while(r-l>=eps)
{
double mid=(l+r)/2;
if(check(mid)) r=mid,ans=mid;
else l=mid;
}
printf("%.2Lf\n",ans);
return 0;
}