【BZOJ2328】 [HNOI2011]赛车游戏

BZOJ2328 [HNOI2011]赛车游戏

前言

这道题目我真的佛了,卡精度+卡时间这就是下一个聊天鬼才.

Solution

首先可以二分出最大速度,然后考虑下坡的话可能有更好的解,然后这样子算一下就好了.

代码实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<iostream>
#define ll long long
#define re register
using namespace std;
inline int gi(){
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=(sum*10)+ch-'0';ch=getchar();}
    return f*sum;
}
const int N=10010;
const double eps=1e-15;
struct node
{
	double x,y,k,len;
}p[N];
int n;
double a,b,mx,f;
bool check(double mid)
{
	double need=0.0;
	for(int i=1;i<=n;i++)
	{
		need+=max(a*mid+b*p[i].k,0.0)*p[i].len;
		if(need+eps>=f)return false;
	}
	return true;
}
double calc(double V)
{
	double res=0.0;
	for(int i=1;i<=n;i++)
	{
		double tmp=a*V+b*p[i].k;
		if(tmp<=eps)
		{
			double v=(-b*p[i].k)/a;
			v=min(v,mx);
			res+=p[i].len/v;
		}
		else
		{
			if(V<=eps)return 0;
			res+=p[i].len/V;
		}
	}
	return res;
}
void solve()
{
	double l=0,r=mx;int times=0;
	while(times<=500)
	{
		double mid=(l+r)/2.0;
		if(check(mid))l=mid;
		else r=mid;
		times++;
	}
	double Time=calc(l);
	if(Time<=eps)puts("IMPOSSIBLE");
	else printf("%.5lf
",Time);
}
int main(){
	int T=gi();
	while(T--)
	{
		scanf("%lf%lf%lf%lf%d",&a,&b,&mx,&f,&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%lf%lf",&p[i].x,&p[i].y);
			p[i].x/=1000.0;p[i].y/=1000.0;
			p[i].k=p[i].y/p[i].x;
			p[i].len=sqrt(p[i].x*p[i].x+p[i].y*p[i].y);
		}
		solve();
	}
	return 0;
}
原文地址:https://www.cnblogs.com/mleautomaton/p/10349367.html