首页 > 其他分享 >【BZOJ1857】【SCOI2010】传送带(三分套三分)

【BZOJ1857】【SCOI2010】传送带(三分套三分)

时间:2022-10-28 18:46:43浏览次数:37  
标签:p1 Point BZOJ1857 double mid eps 2.0 三分 SCOI2010

三分的第一道入手题。

三分是个什么样的东西呢?我用一个例题来解释:

给你一段序列,保证有且仅有一个位置 \(i\),使得 \(i\) 左边的序列单调递增,\(i\) 右边的序列单调递减,请你找出这个位置 \(i\)

这个问题形象的解释就是有一座山峰,问你这座山峰的最高点在哪里。

那么我们可以用到三分法来解决。三分像二分一样,有一个询问区间 \(l\)、\(r\),也就是我们确定答案就在这个区间内。我们每次先像二分一样求出 \(mid\),然后我们找出两个数:\(mid_l\)、\(mid_r\),分别为 \(mid\) 的左边一位上的数和右边一位上的数,然后比较 \(mid_l\) 和 \(mid_r\) 的大小。由于从 \(mid_l\) 到 \(mid_r\) 肯定是单调递增的(除非 \(mid\) 就是我们要找的那个数,这种情况要特判),所以若 \(mid_l<mid_r\),则我们要找的位置肯定在 \(l\sim mid_r\) 之间,所以 \(r=mid_r\)。否则就是 \(l=mid_l\)。

那么这一题怎么做呢?我们用三分套三分,第一个三分枚举第一条线段上的转向点 \(M\),第二个三分枚举第二条线段上的转向点 \(N\)。

代码如下:

#include<bits/stdc++.h>

#define eps 1e-4

using namespace std;

struct Point
{
	double x,y;
	void read()
	{
		scanf("%lf%lf",&x,&y);
	}
	void write()
	{
		printf("%lf %lf\n",x,y);
	}
	Point(){};
	Point(double xx,double yy)
	{
		x=xx,y=yy;
	}
}a,b,c,d;

bool operator == (Point a,Point b)
{
	return a.x==b.x&&a.y==b.y;
}

struct Line
{
	double k,b;
	void get(Point p1,Point p2)
	{
		k=(p1.y-p2.y)/(p1.x-p2.x);
		b=p1.y-k*p1.x;
	}
}AB,CD;

double p,q,r,ans;

double find1(Line l,double x)
{
	return l.k*x+l.b;
}

double dis(Point a,Point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double calc2(Point p1,Point p2)
{
	return dis(p1,p2)/r+dis(p2,d)/q;
}

double calc1(Point p1)
{
	if(c==d)
		return dis(a,p1)/p+dis(p1,c)/r;
	double ans;
	if(c.x!=d.x)
	{
		double l=c.x,r=d.x,ans;
		if(l>r)swap(l,r);
		while(r-l>eps)
		{
			double mid=(l+r)/2.0;
			double mid1=mid-eps/2.0,mid2=mid+eps/2.0;
			double dis1=calc2(p1,Point(mid1,c.y!=d.y?find1(CD,mid1):c.y));
			double dis2=calc2(p1,Point(mid2,c.y!=d.y?find1(CD,mid2):c.y));
			if(dis1<dis2)
				ans=dis1,r=mid-eps;
			else
				ans=dis2,l=mid+eps;
		}
		return dis(a,p1)/p+ans;
	}
	else
	{
		double l=c.y,r=d.y,ans=0;
		if(l>r)swap(l,r);
		while(r-l>eps)
		{
			double mid=(l+r)/2.0;
			double mid1=mid-eps/2.0,mid2=mid+eps/2.0;
			double dis1=calc2(p1,Point(c.x,mid1));
			double dis2=calc2(p1,Point(c.x,mid2));
			if(dis1<dis2)
				ans=dis1,r=mid-eps;
			else
				ans=dis2,l=mid+eps;
		}
		return dis(a,p1)/p+ans;
	}
}

int main()
{
	a.read(),b.read(),c.read(),d.read();
	AB.get(a,b),CD.get(c,d);
	scanf("%lf%lf%lf",&p,&q,&r);
	if(a==b&&c==d)
	{
		printf("%.2lf\n",dis(a,c));
		return 0;
	}
	if(a==b)
	{
		printf("%.2lf\n",calc1(a));
		return 0;
	}
	double ans;
	if(a.x!=b.x)
	{
		double l=a.x,r=b.x;
		if(l>r)swap(l,r);
		while(r-l>eps)
		{
			double mid=(l+r)/2.0;
			double mid1=mid-eps/2.0,mid2=mid+eps/2.0;
			double dis1=calc1(Point(mid1,a.y!=b.y?find1(AB,mid1):a.y));
			double dis2=calc1(Point(mid2,a.y!=b.y?find1(AB,mid2):a.y));
			if(dis1<dis2)
				ans=dis1,r=mid-eps;
			else 
				ans=dis2,l=mid+eps;
		}
	}
	else
	{
		double l=a.y,r=b.y;
		if(l>r)swap(l,r);
		while(r-l>eps)
		{
			double mid=(l+r)/2.0;
			double mid1=mid-eps/2.0,mid2=mid+eps/2.0;
			double dis1=calc1(Point(a.x,mid1));
			double dis2=calc1(Point(a.x,mid2));
			if(dis1<dis2)
				ans=dis1,r=mid-eps;
			else 
				ans=dis2,l=mid+eps;
		}
	}
	printf("%.2lf\n",ans);
}
/*
0 0 0 100
100 0 100 100
2 2 1
*/

标签:p1,Point,BZOJ1857,double,mid,eps,2.0,三分,SCOI2010
From: https://www.cnblogs.com/ez-lcw/p/16837099.html

相关文章

  • 【鸟哥杂谈】三分钟完成腾讯云部署emqx,公网访问自己的mqtt服务器
    忘记过去,超越自己❤️博客主页​​单片机菜鸟哥,一个野生非专业硬件IOT爱好者​​❤️❤️本篇创建记录2022-10-15❤️❤️本篇更新记录2022-10-15❤️......
  • 《三分钟漫画汽车史》
    我之前是一个汽车小白,仅仅识得宝马、奔驰、奥迪、大众、丰田、别克等几种街头常见车的车标。读完本书后,我也能识得标致、斯柯达、布加迪、阿尔法·罗密欧、阿斯顿·马丁、......
  • 三分支网络——目前目标检测性能最佳网络框架
    尺度变化是目标检测中的关键挑战之一。今天要说的这个技术就特别厉害,在目标检测领域中,目前是性能最强的一个框架。下面让我们一起去见证下它的优势所在。本次介绍的算法框架......
  • 三分钟学会短信验证
    一:打开APISpace官网,登录,搜索短信验证,点击立即购买,新用户会送十条短信https://www.apispace.com/       二:打开我的Api,找到刚刚购买的短信流量包,复制提供......
  • Meeting on the Line(贪心,二分,三分)
    MeetingontheLine(贪心算法)(二分,三分)题目大意:类似(实数版)货仓选址,给你n个位置(不用再这n个位置中选,可以任意选实数),再给你这n个位置出发的准备时间(可以转化成距离来看),求一......
  • 货仓选址(贪心)(也可以二分)(还可以三分)
    货仓选址(贪心)题目大意:给你N个位置(在同一条轴上的),求出在这些位置中的一个位置,使得所有位置到这个位置的和最小利用贪心思想,如果选取的位置不在中心,那么向左或者向右移动......
  • P2569 [SCOI2010]股票交易 题解
    设\(f_{i,j}\)表示第1天至第\(i\)天,手上有\(j\)股股票时拥有的最多钱。考虑转移,首先就有\(f_{i,j}=-j\timesap_i\)即单纯买入,然后由转移方程定义有\(f_{i,j}=......
  • 【三分小记】
    众所周知,三分可以求单峰函数极值那么首先要明确单峰函数的定义:它们有唯一的极大值点,在极大值左侧严格单调上升,右侧严格单调下降(单谷函数相反)注意单峰函数并不一定是凸函......
  • 三分钟读懂什么是动作捕捉
    动作捕捉技术是一项抓取现实动作,建立数据模型,随后形成虚拟角色。众所周知的《阿凡达》、《指环王》、《复联》系列等电影,全程采用动捕技术拍摄。以前,动画只能靠画师想象抠......
  • 二分、三分、01分数规划
    二分、三分、01分数规划二分查找单调函数求零点二分查找:在一个单调有序的集合中查找元素,每次将集合分为左右两个部分,判断解在哪个部分中并调整集合上下界,重复直到找到目......