[UVa 10385] Duathlon 三分法

来源:互联网 发布:石油化工数据 编辑:程序博客网 时间:2024/06/03 11:16

题目传送门:1.UVa 原网站

2.Vjudge (方便打开)   

题目大意:本题含有多组测试数据。n 个选手参加比赛,比赛分为跑步和骑车两项,跑步的距离为 r km,骑车的距离为 k km,且总长为 ( r + k ) = t。已知每位选手分别进行两种项目时的速度 V1 , V2。其中,有一名选手对裁判员进行了贿赂,希望获得冠军,求:是否可以通过调整各项目的距离使这一名选手获胜。如果可以获胜,还需输出与第二名的耗时之差的最大值及此时各项目的距离。如果不能,则输出 -1。( n ≤ 20 , t ≤ 100 )


题目分析:

由题,通过分析,我们发现这名“贿赂者”选手与其它选手中最优者耗时之差为单峰函数,于是可以进行三分操作。(你问我为什么是单峰函数?把距离设为横轴,耗时之差设为纵轴,然后对于不同的距离求出不同的耗时之差,画个图就出来了,就是这样)

三分操作的方法:设答案的下界为 left,上界为 right;然后对于 left ~ right 之间的两个三分点设为 lm 和 rm,其中 lm = left + ( right - left ) / 3,rm = right - ( right - left ) / 3。如果该函数为上凸函数,当 lm < rm 时,那么就在 [ lm , right ] 之内查找,否则在 [ left , rm ] 内查找;如果该函数为下凸函数,当 lm < rm 时,那么就在 [ left , rm ] 之间查找,否则在 [ lm , right ] 内查找。

如果还有疑问,请戳这里:http://blog.csdn.net/u012469987/article/details/50897291


下面附上代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MXer = 22;const double esp = 1e-5;const double INF = 1e13;int t,n;double run[MXer],cycle[MXer];//跑步和骑车分别花的时间 double judge(double val){//判断耗时之差  double mint = INF;for (int i = 1;i < n;i++){double tmp = (val / run[i]) + (t - val) / cycle[i];if (tmp < mint) mint = tmp;}double cheater = (val / run[n]) + (t - val) / cycle[n];return cheater - mint;}int main(){while (scanf("%d",&t) != EOF){double lf = 0.0,rt = t * 1.0;//表示 R 的值 memset(run,0,sizeof(run));memset(cycle,0,sizeof(cycle));cin>>n;for (int i = 1;i <= n;i++){cin>>run[i]>>cycle[i];}double lm = lf + ( rt - lf ) / 3,rm = rt - ( rt - lf ) / 3;while (rt - lf > esp){lm = lf + ( rt - lf ) / 3,rm = rt - ( rt - lf ) / 3;if (judge(lm) < judge(rm)){rt = rm;} else {lf = lm;}}if (judge(lf) < 0){//最好情况下比第二名快 printf("The cheater can win by %0.0lf seconds with r = %0.2lfkm and k = %0.2lfkm.\n",judge(lf) * (-3600),lf,t - lf);//把超越的时间(负数)变成正的秒数 } else {//比第二名慢 printf("The cheater cannot win.\n");}}return 0;}


原创粉丝点击