Road to Cinema(贪心+二分)
https://www.cnblogs.com/flipped/p/6083973.html 原博客转载
http://codeforces.com/group/1EzrFFyOc0/contest/738/problem/C 题目链接
题意:n个价格c[i],油量v[i]的汽车,求最便宜的一辆使得能在t时间内到达s,路途中有k个位置在g[i]的加油站,可以免费加满油,且不耗时间。每辆车有两种运行模式可以随时切换:1.每米一分钟两升油;2.每米两分钟一升油。
题解:二分求可以到达s的最小油量。对于油量v,能到达s的条件是:油量足够经过最长路程(中途不能加油);总的最小时间不超过t。为了求最小时间,可以用线性规划:一段不加油的路程长度为l,假设x米运行的是1.模式,则l-x米运行的是2.模式。总时间为t。则有
t=x+2∗(l−x)
v≥x∗2+l−x
x≥0l−x≥0(1)
{ t=x+2∗(l−x)
v≥x∗2+l−x
x≥0
l−x≥0
化简一下:
t=2∗l−x
x≤v−l
l≥x≥0(2)
{t=2∗l−x
x≤v−l
l≥x≥0
最后得到:
tmin=2∗l−xmax
=2∗l−min(v−l,l)
=max(l∗3−v,l)tmin
=2∗l−xmax
=2∗l−min(v−l,l)
=max( l∗3−v,l )
且v≥l,可以改为v≥max(l)。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<set> 7 #include<vector> 8 #include<stack> 9 #include<queue> 10 #include<map> 11 using namespace std; 12 #define ll long long 13 #define se second 14 #define fi first 15 const int Mos = 0x7FFFFFFF; //2147483647 16 const int nMos = 0x80000000; //-2147483648 17 const int N=2e5+5; 18 19 int n,k,s,t,dis; 20 int c[N],v[N],g[N]; 21 22 bool check(int vv) //油量 23 { 24 if(vv<dis) return 0; //如果开低速的油都不够 25 int sumt=0; 26 for(int i=1;i<=k+1;i++) 27 { 28 sumt+= max(g[i],3*g[i]-vv); 29 if(sumt>t) return 0; //超出时间 30 } 31 return 1; 32 } 33 int main() 34 { 35 cin>>n>>k>>s>>t; 36 for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&v[i]); 37 for(int i=1;i<=k;i++) scanf("%d",&g[i]); 38 g[k+1]=s; 39 sort(g+1,g+1+k); 40 for(int i=k+1;i>=1;i--) 41 dis=max(dis,g[i]-=g[i-1]); //找出加油站间最长间隔,顺便把g[i]变为距离前面一个的距离 42 int l=0,r=1e9+5,mid,res=0; 43 while(l<=r) //二分找出最少需要的油量; 44 { 45 mid=(l+r)>>1; 46 if( check(mid) ) r=mid-1,res=mid; //记录最优的res 47 else l=mid+1; 48 } 49 int ans=1e9+1; 50 if(res) 51 for(int i=1;i<=n;i++) 52 if(v[i]>=res) ans=min(ans,c[i]); 53 if(ans>=1e9+1) ans=-1; 54 55 cout<<ans<<endl; 56 }