[Codeforces 8D] Two Friends
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的更多相关文章
- codeforces 8D Two Friends 二分+ 判断三个圆是否有公共交点
题目链接 有两个人x, y, 现在在A点, x要直接去B点, y要先去C点在去B点, 现在给出x, y两人可以行走的最大距离T1, T2, 求出他们从A点出发之后, 可以走的最长的公共路径. 我们先看 ...
- Codeforces 8D Two Friends 三分+二分+计算几何
题目链接:点击打开链接 题意:点击打开链接 三分house到shop的距离,二分这条斜边到cinema的距离 #include<stdio.h> #include<string.h& ...
- CodeForces 8D Two Friends 判断三个圆相交
题意: 有两个人\(Alan\)和\(Bob\),他们现在都在\(A\)点,现在\(Bob\)想去\(B\)点,\(Alan\)想先到\(C\)点再去\(B\)点. \(Alan\)所走的总路程不能超 ...
- Questions(Updating)
有时候做题时会遇到一些未学习的零碎知识点,或存疑的疑惑 为防止遗忘,在此记录 1.复数除法与线性变换的关系 Accepted Codeforces 8D(2018.5.9) Definition: 复 ...
- Mistakes(Updating)
1.当调试时发现无法正常调用函数时,检查是否发生爆栈 对于每个栈仅有4MB的空间,开int只能开大约5*10^5. 大数组一定要开全局变量 2.当long long=int*int时会爆int,一定要 ...
- Codeforces Round #219 (Div. 1)(完全)
戳我看题目 A:给你n个数,要求尽可能多的找出匹配,如果两个数匹配,则ai*2 <= aj 排序,从中间切断,分成相等的两半后,对于较大的那一半,从大到小遍历,对于每个数在左边那组找到最大的满足 ...
- Codeforces Round #509 (Div. 2) F. Ray in the tube(思维)
题目链接:http://codeforces.com/contest/1041/problem/F 题意:给出一根无限长的管子,在二维坐标上表示为y1 <= y <= y2,其中 y1 上 ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
随机推荐
- wyh的天鹅~vector的使用
链接:https://www.nowcoder.com/acm/contest/93/L来源:牛客网 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 关于fragment点击能穿透问题
本人在做项目的过程中遇到的这个问题,然后就在网上百度了一下,之后也是在csdn上看到博友发过此类问题的解决办法,所以特此重新总结一下,顺便也给自己提个醒,避免出现此类问题.好!下面我们说一下问题: 举 ...
- MyBatis对象关联关系----多对多的保存与查询
模拟情景: 对象:学生,课程 关系:一个学生可选多个课程,一门课程可被多个学生选择 一.保存 1.创建数据库表,student,course,student_course,其中student_cour ...
- 2017南宁现场赛E The Champion
Bob is attending a chess competition. Now the competition is in the knockout phase. There are 2^r2r ...
- 【BZOJ1146】【CTSC2008】网络管理 [整体二分]
网络管理 Time Limit: 50 Sec Memory Limit: 162 MB[Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司,在 ...
- bzoj 2659 几何
首先考虑(0, 0)到(p, q)这条直线. y = q / p * x. sum{k = 0 to (p - 1) / 2} [q / p * k] 就是直线下方的点数.sum{k = 0 to ( ...
- LCD实验学习笔记(四):系统时钟
一般CPU频率(FCLK)高于内存.网卡等设备频率(HCLK),而串口.USB.I2C等设备频率(PCLK)更低. 系统时钟: 系统时钟源为晶振,初始频率12MHz. 通过设置MPLLCON寄存器的M ...
- 用 C# 代码如何实现让你的电脑关机,重启,注销,锁定,休眠,睡眠
简介 本文讲述了用 C# 代码如何实现让你的电脑关机,重启,注销,锁定,休眠,睡眠. 如何实现 首先,使用 using 语句添加我们需要的命名空间: using System.Diagnostics; ...
- 设置session过期时间
1如下是登录注册和记住密码的功能: # -*- coding: utf-8 -*- def cms_login(request): if request.method == 'GET': return ...
- HDU 4344 大数分解大素数判定
这里贴个模板吧.反正是不太理解 看原题就可以理解用法!! #include <cstdio> #include <iostream> #include <algorith ...