UVA1753 Need for Speed
2019-10-28
OIer写代码,总会遇到几个玄学错误。
题意描述
Winniechen有一辆车, 但是它的迈速表指针坏掉的。当度数为的时候, 车的实际速度是 , 是一个不确定的实数(常数。现在给你一段行程,包含n个路段, 保证每个路段是均速行驶的, 每个描述有两个数字, 分别为行驶的路程和迈速表的读数。整个行程一共用了的时间, 请确定的值。另外请注意, 他的真实速度是永远保持在0以上的。
Solve
首先,我们蒙一个做答案。
然后试一试,如果用时超过的话,就是速度太慢了,应该给他提提速。如果小于的话,就是速度太快了,应该给他降一降,如果用时等于的话,bingo,恭喜你猜对了。
所以,我们惊奇的发现,这个具有“单调性”,这意味着什么?我们可以有规律地去猜。
二分答案。而判断就是用用时与的关系。
特殊之处就在于,是实数域上的二分。
无非就是把
while(l<=r){
mid=(l+r)>>1;
if(···) l=mid+1;
else r=mid-1;
}
换成
while(l<=r-eps){
mid=(l+r)/2;
if(···) l=mid;
else r=mid;
}
所有变量都是double类型。eps就是你想要卡的精度。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100000
#define db double
using namespace std;
int n;
db s[N],d[N];
db t,sum;
db l,r,mid,eps=1e-9;//就是这个
bool solve(db c){
sum=0;
for(int i=1;i<=n;i++){
if(s[i]+c<=0) return true;//如果速度小于0的话就跟就GG了
sum+=(d[i]/(s[i]+c));
}
if(sum>t) return true;
else return false;
}
int main()
{
while(scanf("%d%lf",&n,&t)!=EOF){//记住这个“!=EOF”
l=-20000000,r=20000000;
for(int i=1;i<=n;i++) scanf("%lf%lf",&d[i],&s[i]);
for(int i=1;i<=100;i++){
mid=(l+r)/2;
if(solve(mid)) l=mid;
else r=mid;
}
printf("%.9lf\n",l);
}
}
后言
我原以为加不加EOF都一样的,或者是“~”取反,但是某谷给了我一个大大的耳光,我T飞了。
所以观察答案有“单调性”的话,二分莽就完了。