文章目录
E - Road to Cinema
题意:
某人在起点
0
0
0处,到终点的距离为
s
s
s。 公司提供
n
n
n种车,每种车有属性租车费用
c
i
c_i
ci,油箱容量
v
i
v_i
vi,车子有两种前进方式 :慢速:
1
k
m
1km
1km消耗
1
L
1L
1L汽油,花费
2
2
2分钟,快速:
1
k
m
1km
1km消耗
2
L
2L
2L汽油,花费
1
1
1分钟。 路上有
k
k
k个加油站,加油不需要花费时间,且直接给油箱加满。 问在
T
T
T分钟内到达终点的最小花费是多少?,若无法到达终点,输出
−
1
-1
−1
思路:(二分)
二分油量,判断
m
i
d
mid
mid油量是否能在
≤
t
\le t
≤t时间内到达
s
s
s,我们采取贪心的策略如果能快速走就快速走,如果慢速走油都不够直接返回
f
a
l
s
e
false
false,不然就快慢结合
设快走
x
x
x,慢走
y
y
y,两端加油站间距离为
d
i
s
dis
dis,经过时间为
t
t
t,则
x
+
y
=
d
i
s
,
2
∗
x
+
y
=
m
i
d
,
x
+
2
∗
y
=
t
x+y=dis,2*x+y=mid,x+2*y=t
x+y=dis,2∗x+y=mid,x+2∗y=t,解得
t
t
t为
3
∗
d
i
s
−
m
i
d
3*dis-mid
3∗dis−mid,把每段得
t
t
t相加,判断是否
≤
T
\le T
≤T,需要注意加油站的边界问题,题目有很多小细节具体见代码
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define mst(a,x) memset(a,x,sizeof(a));
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define int long long
typedef long long ll;
typedef pair<int,int> PII;
const int N=1e6+10;
const int mod=1e9+7;
int n,k,s,T;
int c[N],v[N];
int g[N];
bool check(int mid)
{
int t=0;
rep(i,1,k+1)
{
int dis=g[i]-g[i-1];//每一段的距离
//cout<<"--"<<dis<<endl;
if(mid<dis) return false; //如果慢速都走不到
if(dis*2<=mid) t+=dis; //快速走的油量小于mid就可以走
else t+=3*dis-mid; //快慢混合
//cout<<"----"<<t<<endl;
if(t>T) return false;
}
return true;
}
void solve()
{
cin>>n>>k>>s>>T;
rep(i,1,n) cin>>c[i]>>v[i];
rep(i,1,k) cin>>g[i];
sort(g+1,g+1+k);
g[0]=0;//初始点在0
g[k+1]=s;//终点在s
int l=0,r=2e9;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
int ans=2e9;
rep(i,1,n)
if(v[i]>=r) ans=min(ans,c[i]);
if(ans==2e9) cout<<-1; //如果没有符合的车输出-1
else cout<<ans;
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//int t;cin>>t;while(t--)
solve();
return 0;
}