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;
}