Brief Introduction:

有两人a、b,他们都在A点,a经过B点到C点,而b直接到C点。a走过的距离不超过la,b走过距离不超过lb,询问他们可能经过最长的公共距离。

Algorithm1:

我们首先可以发现一个公共距离是否可行是具有单调性的

从而可以考虑使用二分

于是我们将问题转化为已知三个圆,询问着三个圆是否有公共部分

对于这类问题,我们每次求出三个圆中两两的交点,判断其是否在第三个圆内即可

Algorithm2:

我们假设公共路径在AD上,D在线段BC上,我们可以发现在D从B移动到C时,最长公共距离的长度是凸性函数

我们由此想到三分法

而对于每一个特定的D点,其公共距离的长度同算法1一样具有单调性,使用二分法即可

Code1:

#include <bits/stdc++.h>

using namespace std;
const double eps=1e-; #define point complex<double> point a,b,c;
double AB,BC,AC,ta,tb; void Read(point &k)
{
double x,y;cin >> x >> y;
k=point(x,y);
} bool intersect(point a,double Ra,point b,double Rb,point c,double Rc)
{
if(abs(a-b)-(Ra+Rb)>eps) return false;
if(abs(a-c)-Ra<eps && abs(b-c)-Rb<eps) return true;
if(abs(a-b)+Ra-Rb<-eps || abs(a-b)+Rb-Ra<-eps) return false; b-=a;c-=a;
point i=point(b.real()/abs(b),b.imag()/abs(b)); //对原图进行线性变换,求出新的基向量
b/=i;c/=i; double x=(Ra*Ra-Rb*Rb+abs(b)*abs(b))/(*abs(b)); //用勾股定理求交点 double h=sqrt(max(Ra*Ra-x*x,0.0)); if(abs(point(x,h)-c)-Rc<eps || abs(point(x,-h)-c)-Rc<eps) return true; //对上下两个交点都进行判断
return false;
} bool eval(point a,double Ra,point b,double Rb,point c,double Rc) //查看两两的交点是否在第三圆内
{
if(Ra<eps || Rb<eps || Rc<eps) return false;
if(intersect(a,Ra,b,Rb,c,Rc)) return true;
if(intersect(a,Ra,c,Rc,b,Rb)) return true;
if(intersect(b,Rb,c,Rc,a,Ra)) return true;
return false;
} int main()
{
cout.setf(ios::fixed);
cout.precision(); cin >> ta >> tb;
Read(a);Read(c);Read(b);
AC=abs(a-c);AB=abs(a-b);BC=abs(b-c); ta+=AB+BC;tb+=AC;
if(tb-(AB+BC)>-eps)
return cout << min(tb,ta),; double l=,r=min(ta,tb);
while(fabs(r-l)>eps) //对答案二分
{
double m=(r+l)*.;
if(eval(a,m,b,ta-BC-m,c,tb-m)) l=m;
else r=m;
}
cout << (r+l)*.;
return ;
}

Code2:

#include <bits/stdc++.h>

using namespace std;
const double eps=1e-; struct Point
{
double x,y;
Point(){}
Point(double a,double b){x=a,y=b;}
void input(){cin >> x >> y;}
double dist(Point&a){return hypot(x-a.x,y-a.y);}
}; double ta,tb,w,AB,AC,BC,AU,UB,UC,lm,rm;
Point A,B,C; double eval(double k)
{
Point U=Point(k*B.x+(-k)*C.x,k*B.y+(-k)*C.y);
AU=A.dist(U),UB=U.dist(B),UC=U.dist(C);
if(AU+UB<ta && AU+UC<tb)
return min(ta-UB,tb-UC); double l=,r=;
while(fabs(l-r)>eps) //二分
{
w=(l+r)*0.5;
Point V=Point(w*U.x+(-w)*A.x,w*U.y+(-w)*A.y);
if(w*AU+V.dist(B)<ta && w*AU+V.dist(C)<tb) l=w;
else r=w;
}
return (l+r)*0.5*AU;
} int main()
{
cout.setf(ios::fixed);
cout.precision();
cin >> ta >> tb;
A.input();C.input();B.input();
AB=A.dist(B),AC=A.dist(C),BC=B.dist(C); ta+=AB+1e-;tb+=AC+1e-; //先加上eps,解决精度问题 if(tb>AB+BC)
{
cout << min(tb,ta+BC);
return ;
} double l=,r=;
while(fabs(l-r)>eps) //三分
{
lm=(*l+r)/,rm=(*r+l)/;
if(eval(lm)>eval(rm)) r=rm;
else l=lm;
}
cout << eval((l+r)*0.5);
return ;
}

Review:

1、使用complex类解决计算几何问题

使用abs、hypot函数

2、线性变换

首先确定原点A,求出其它坐标与原点的相对位置

其次求出单位向量P(Xb/abs,Yb/abs),将AB作为X轴

最后使用复数除法,将其它向量除去单位向量,确定新的坐标

3、判断三圆是否有公共部分:

两两使用勾股定理判交点是否在第三个圆内

4、在无法确定某个距离时,寻找其中的凸性或单调性,用三分或二分解决

      计算几何的常用策略

5、精度问题:一般选择超出答案要求的2到3位,过少会WA,过多会TLE

[Codeforces 8D] Two Friends的更多相关文章

  1. codeforces 8D Two Friends 二分+ 判断三个圆是否有公共交点

    题目链接 有两个人x, y, 现在在A点, x要直接去B点, y要先去C点在去B点, 现在给出x, y两人可以行走的最大距离T1, T2, 求出他们从A点出发之后, 可以走的最长的公共路径. 我们先看 ...

  2. Codeforces 8D Two Friends 三分+二分+计算几何

    题目链接:点击打开链接 题意:点击打开链接 三分house到shop的距离,二分这条斜边到cinema的距离 #include<stdio.h> #include<string.h& ...

  3. CodeForces 8D Two Friends 判断三个圆相交

    题意: 有两个人\(Alan\)和\(Bob\),他们现在都在\(A\)点,现在\(Bob\)想去\(B\)点,\(Alan\)想先到\(C\)点再去\(B\)点. \(Alan\)所走的总路程不能超 ...

  4. Questions(Updating)

    有时候做题时会遇到一些未学习的零碎知识点,或存疑的疑惑 为防止遗忘,在此记录 1.复数除法与线性变换的关系 Accepted Codeforces 8D(2018.5.9) Definition: 复 ...

  5. Mistakes(Updating)

    1.当调试时发现无法正常调用函数时,检查是否发生爆栈 对于每个栈仅有4MB的空间,开int只能开大约5*10^5. 大数组一定要开全局变量 2.当long long=int*int时会爆int,一定要 ...

  6. Codeforces Round #219 (Div. 1)(完全)

    戳我看题目 A:给你n个数,要求尽可能多的找出匹配,如果两个数匹配,则ai*2 <= aj 排序,从中间切断,分成相等的两半后,对于较大的那一半,从大到小遍历,对于每个数在左边那组找到最大的满足 ...

  7. Codeforces Round #509 (Div. 2) F. Ray in the tube(思维)

    题目链接:http://codeforces.com/contest/1041/problem/F 题意:给出一根无限长的管子,在二维坐标上表示为y1 <= y <= y2,其中 y1 上 ...

  8. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  9. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

随机推荐

  1. 【AtCoder】ARC 081 E - Don't Be a Subsequence

    [题意]给定长度为n(<=2*10^5)的字符串,求最短的字典序最小的非子序列字符串. http://arc081.contest.atcoder.jp/tasks/arc081_c [算法]字 ...

  2. taotao单点登录的用户Controller、service(注册、登录、验证是否登录方法)

    接口文档: 1.1. 注册接口 1.1.1. 检查数据是否可用 请求方法 GET URL http://sso.taotao.com/user/check/{param}/{type} 参数说明 格式 ...

  3. fuser命令找到占用资源的进程

    fuser 概述 fuser命令是用来显示所有正在使用着指定的file, file system 或者 sockets的进程信息. 例一: #fuser –m –u /mnt/usb1 /mnt/us ...

  4. 【BZOJ】5028: 小Z的加油店

    [算法]数学+线段树/树状数组 [题解] 首先三个操作可以理解为更相减损术或者辗转相除法(待证明),所以就是求区间gcd. 这题的问题在线段树维护gcd只能支持修改成一个数,不支持加一个数. 套路:g ...

  5. MyBatis系列四 之 智能标签进行查询语句的拼接

    MyBatis系列四 之 智能标签进行查询语句的拼接 使用Foreach进行多条件查询 1.1 foreach使用数组进行多条件查询 在MyBatis的映射文件中进行如下配置 <!--根据数组进 ...

  6. python基础===正则表达式(转)

    正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能 ...

  7. PL/SQL 06 函数 function

    --函数 create or replace function  函数名称(参数1 类型1,参数2 类型2,...)  return 数据类型as  变量.常量声明;begin  代码;end; cr ...

  8. HashMap/Hashtable/ConcurrentHashMap区别

    HashMap:每个隔间都没锁门,有人想上厕所,管理员指给他一个隔间,里面没人的话正常用,里面有人的话把这个人赶出来然后用. 优点,每个人进来不耽误都能用:缺点,每一个上厕所的人都有被中途赶出来的危险 ...

  9. 输入法出现 footer被挤上去的问题

    /** * 修改点击input输入框时的位置 *input框获取焦点footer隐藏,失去焦点时显示 */ $('.input-footer-none').on('focus',function(){ ...

  10. mpvue-小程序之蹲坑记

    1. 不支持 v-html 小程序里所有的 BOM/DOM 都不能用,也就是说 v-html 指令不能用 部分复杂的 JavaScript 渲染表达式 {{}} 双花括号的部分,直接编码到 wxml ...