20级CUSTACM 2021年暑期训练七

文章目录


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,2x+y=mid,x+2y=t,解得 t t t 3 ∗ d i s − m i d 3*dis-mid 3dismid,把每段得 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值