[SCOI2010]传送带,洛谷P2571,三分套三分

正题

      题目给出A,B,C,D的坐标,要你求AB,CD上两个点E,F,使得Ans=dis(A,E)/P+dis(E,F)/R+dis(F,D)/Q

      首先我们先固定点E,移动F。

      1.F肯定存在一个唯一的最小点使得当前E的Ans最小。

      2.其他的一定从这个点开始往两边单调上升。

      这两个都可以很好的感性理解。

      那么下凹函数三分就可以了。

      那么我们又可以发现对于每一个E的Ans,他们也是组成了一个下凹函数。

      三分内用三分算答案即可。注意这里的正负性,要用abs。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;

struct node{
	double x,y;
	friend node operator+(const node a,const node b){return (node){a.x+b.x,a.y+b.y};}
	friend node operator/(const node a,int x){return (node){a.x/x,a.y/x};}
	friend node operator-(const node a,const node b){return (node){a.x-b.x,a.y-b.y};}
}a,b,c,d;
double qw,we,er;
double q=0.00001;
double dis1,dis2;

double get_dis(node x,node y){
	return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}
double get_ans(node k){
	node l=c,r=d;
	double ans;
	while(fabs(r.x-l.x)>q || fabs(r.y-l.y)>q){
		node mid1=l+(r-l)/3,mid2=(mid1+r)/2;
		double f1=get_dis(a,k)/qw+get_dis(k,mid1)/er+get_dis(mid1,d)/we,f2=get_dis(a,k)/qw+get_dis(k,mid2)/er+get_dis(mid2,d)/we;
		if(f1>f2) l=mid1;
		else r=mid2;
		ans=min(f1,f2);
	}
	return ans;
}

int main(){
	scanf("%lf %lf %lf %lf",&a.x,&a.y,&b.x,&b.y);
	scanf("%lf %lf %lf %lf",&c.x,&c.y,&d.x,&d.y);
	scanf("%lf %lf %lf",&qw,&we,&er);
	dis1=get_dis(a,b);
	dis2=get_dis(c,d);
	node l=a,r=b;
	double ans;
	do{
		node mid1=l+(r-l)/3,mid2=(mid1+r)/2;
		double f1=get_ans(mid1),f2=get_ans(mid2);
		if(f1>f2) l=mid1;
		else r=mid2;
		ans=min(f1,f2);
	}while(fabs(r.x-l.x)>=q || fabs(r.y-l.y)>=q);
	printf("%.2lf",ans);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值