排队

来源:互联网 发布:梦里花落知多少演员表 编辑:程序博客网 时间:2024/05/01 17:00

问题描述

Nc参加完比赛之后,实在是太累了,就直接倒在床上睡了过去,慢慢的他就进入了梦乡。Nc梦到他变成了一名军人,他正在给一些刚入伍的军人进行军训,这些军人分别站在N个点上,每个点坐标为Pi, 一个点上有ci个军人,这样显的非常不好看,Nc很不爽,他想让队伍展开,但是只能站成一排,每个人之间的距离不能小于limit。假设军人的移动速度为1,那么Nc想知道最快多久使队伍符合他的要求.


输入文件

第一行一个整数T ,输入包含T组数据.
接下来T组数据,第一行 两个整数n,limit,接下来n行 每行两个整数pi,ci. 输入保证pi单调递增.


输出文件

对于每组数据 输出Case #k: ans. 代表满足Nc要求的最小时间(保留6位小数). K表示是第几组测试数据. 冒号后面有空格.


输入样例

2
3 2
0 1
3 2
6 1
2 2
0 3
1 1


输出样例

Case #1: 1.000000
Case #2: 2.500000


数据范围和约定

对于30% 的数据, n<=20; limit<=5;
对于100% 的数据,n<=200; limit<=10^6; 0 <= | pi |<=100000 ; ci的和不超过10^6; T<=50;


分析

这个题目对于一数据点的为需花费的最小时间为ans,那么显然ans+1,ans+2….都可以满足题目,故我们可以二分答案。

对于极端答案,假设limit=10^6,n=1,c1=10^6,此时可以达到最大消费,ans=5*10^11,所以我们就知道答案在[0,5*10^11]内

然后就是要检查答案是否合理,运用贪心的思想,我们让最左端那位同志往左边走ans个单位,然后我们的左起第二位同志就最少走到p[1]-ans+limit的地方…以此类推可以了


代码

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>#include <iomanip>using namespace std;typedef long long LL;LL p[250];LL c[250];LL n,lim,T;LL read();void binary(double,double);bool check(double);int main(){    freopen("pd.in","r",stdin);    freopen("pd.out","w",stdout);    cout << setiosflags(ios::fixed) << setprecision(6);    T = read();    for(int TTT=1;TTT<=T;++TTT){        n=read(),lim=read();        for(int i=1;i<=n;++i)            p[i]=read(),c[i]=read();        c[1]--;        cout << "Case #" << TTT << ": ";        binary(0,1E12);    }       return 0;}LL read(){    LL in=0;    LL flag=1;    char ch=getchar();    while(ch<'0' || ch>'9'){        if(ch=='-')            flag = -1;        ch = getchar();    }    while(ch>='0' && ch<='9'){        in = in*10+ch-'0';        ch = getchar();    }    return in*flag;}void binary(double left,double right){    double m;    while(right-left > 0.0000001){        m = (left+right)/2;        if(check(m)){            if(right == m)break;            right = m;        }        else{            if(left == m)break;            left = m;        }    }    cout << (left+right)/2 << endl;}bool check(double t){    double place = p[1]-t+lim;    for(int i=1;i<=n;++i)        if(place >= p[i]){            if(place-p[i]+(c[i]-1)*lim < t)                place = place+c[i]*lim;            else                return false;        }        else{            if(p[i]-t > place)                place = p[i]-t;            place = place+(c[i]-1)*lim;            if(place-p[i] > t)                return false;            place = place+lim;        }    return true;}
0 0