[UVa 10385] Duathlon 三分法

博客探讨了如何使用三分法解决UVa 10385 Duathlon比赛中的问题。参赛者中有一名贿赂者希望获胜,通过分析,发现其与最优选手的耗时差形成单峰函数。文章解释了三分法的原理和操作步骤,并提供了代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目传送门: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.youkuaiyun.com/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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值