cf的地址

因为校强, "咕咕十段"队获得了EC-final的参赛资格

因为我弱, "咕咕十段"队现在银面很大

于是咕咕十段决定进行训练. 周末vp了一场, 这是赛后补题.

vp的时候想到了可以利用边界和切线, 但是没有仔细思考.

后来发现, 找到可以走的边界和切线之后, bfs一下就完事了啊.

题目给的eps限制使得我们可以合法的沿着切线和边界进行行走

关键在于找出"可以走的边界和切线"

如果一条切线在两个切点之间穿过了一个圆, 那么就不走这条切线(肯定可以走中间那个圆的某几条切线)

一条切线可以向两个切点外侧延伸, 直到与某个圆/边界相交.

主要麻烦的地方在于找圆的切线以及内外公切线. 以及我现在竟然能把直线求交写错...

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps = 1e-7;
struct point{
double x, y;
point(double a = 0.0, double b = 0.0):x(a), y(b){}
point operator - (const point &A)const{
return point(x-A.x, y-A.y);
}
point operator + (const point &A)const{
return point(x+A.x, y+A.y);
}
void read(){
scanf("%lf%lf",&x,&y);
}
point rot(double theta)const{
return point(x*cos(theta)-y*sin(theta), x*sin(theta) + y*cos(theta));
}
double length()const{
return sqrt(x*x+y*y);
}
point norm()const {
return point(x/length(), y/length());
}
void output(){
printf("%lf %lf",x,y);
}
}pL, pR, S, T, C[52];
double r[52];
double cross(const point &A, const point &B){
return A.x * B.y -A.y * B.x;
}
struct Line{
point S, dlt;
double tmax, tmin;
Line(){
tmax = 1e20;
tmin = -1e20;
}
Line(point s, point t){
S = s;
dlt = t - s;
tmax = 1e20;
tmin = -1e20;
}
Line(point s, point t, double t1, double t2){
S = s; dlt = t - s;
tmin = t1; tmax = t2;
}
point operator () (const double &t)const{
return S + point(dlt.x*t, dlt.y*t);
}
bool through(const point &p)const {
return fabs(cross(p-S, dlt))<eps;
}
double gett(const point &p)const{
if(fabs(p.x - S.x) > eps){
return (p.x - S.x)/(dlt.x);
}else if(fabs(p.y - S.y)>eps){
return (p.y - S.y)/(dlt.y);
}else{
return 0;
}
}
bool contain(const point &p)const{
if(fabs(cross(p-S, dlt))>eps)return false;
double t = gett(p);
return t>=tmin-eps&&t<=tmax+eps;
}
point getp(double t)const{
return point(S.x+t*dlt.x, S.y+t*dlt.y);
}
void output(){
S.output();(S+dlt).output();
}
}L[6000];
Line tangent(point P, point C, double r, int flag){
double theta = acos(r/(P-C).length());
point v = (P-C).norm();
v = point(v.x*r, v.y*r);
v = v.rot(flag*theta);
point T = C + v;
return Line(P, T);
}
Line tangent_out(point C1, double r1, point C2, double r2, int flag){
if((fabs(r1-r2))<eps){
point v = (C1-C2).norm();
v = point(v.x * r1, v.y * r1);
v = v.rot(flag*acos(-1)/2);
return Line(C1+v, C2+v);
}else{
if(r1>r2){
swap(C1, C2);
swap(r1, r2);
}
//r1<r2
//r1/r2 = (l1)/(l2), l2-l1 = length(C1-C2)
double L = (C1 - C2).length();
L = L * r2/(r2-r1);
point v = (C1-C2).norm();
double theta = flag * acos(r2/L);
v = v.rot(theta);
return Line(C1 + point(v.x*r1, v.y*r1), C2 + point(v.x*r2, v.y*r2));
}
}
Line tangent_in(point C1, double r1, point C2, double r2, int flag){
point v = (C2 - C1);
point P = C1 + point(v.x*r1/(r1+r2), v.y*r1/(r1+r2));
double theta = flag*acos(r1/(P-C1).length());
v = v.norm().rot(theta);
return Line(C1 + point(v.x*r1, v.y*r1), C2 - point(v.x*r2,v.y*r2));
}
int cnt_lines = 0, cnt_lines2 = 0;
point intersect(const Line &L1, const Line &L2){
double C = cross(L1.dlt, L2.dlt);
if(fabs(C)<eps)return point(1e20, 1e20);
else{
double t = cross(L1.S - L2.S, L2.dlt)/cross(L2.dlt, L1.dlt);
return L1(t);
}
}
double mult(const point &P1, const point &P2){
return P1.x*P2.x + P1.y*P2.y;
}
bool between(point P, Line &L){
point S = L.S, T = L.S + L.dlt;
return mult(S-P, T-P) < -eps;
}
bool intersect(Line &L, point C, double r){
double dis = fabs(cross(C-L.S, L.dlt))/L.dlt.length();
if(dis > r - eps)return false;
double theta = acos(dis/r);
int flag = cross(C-L.S, L.dlt) > eps ? (1) : (-1);
point v = L.dlt.norm().rot(flag * acos(-1)/2 + theta);
point p = C + point(v.x*r, v.y*r);
if(between(p, L)){
return true;
}else{
double t = L.gett(p);
if(t < 0 && t > L.tmin){
L.tmin = t;
}
if(t > 0 && t < L.tmax){
L.tmax = t;
}
v = L.dlt.norm().rot(flag * acos(-1)/2 - theta);
p = C + point(v.x*r, v.y*r);
t = L.gett(p);
if(t < 0 && t > L.tmin){
L.tmin = t;
}
if(t > 0 && t < L.tmax){
L.tmax = t;
}
return false;
}
}
int N;
bool visited[6000];
int pre[6000], dis[6000];
int q[6000];
void output(int x, int cnt){
if(pre[x] == 0){
printf("%d\n",cnt);
}else{
output(pre[x], cnt+1);
point p = intersect(L[x], L[pre[x]]);
p.output();printf("\n");
}
}
void bfs(){
int head = 0, tail = 0;
visited[0] = true; dis[0] = 0;//S
for(int i = 1; i <= cnt_lines2; ++i){
if(L[i].contain(S)){
pre[i] = 0; dis[i] = 1;
visited[i] = true;
q[tail++] = i;
}
}
while(head!=tail){
int x = q[head++];
if(L[x].contain(T)){
output(x, 0);
break;
}else{
for(int i=1;i<=cnt_lines2;++i){
if(!visited[i]){
point p = intersect(L[i],L[x]);
if(L[i].contain(p)&&L[x].contain(p)){
q[tail++] = i;
visited[i] = true;
pre[i] = x;
dis[i] = dis[x] + 1;
}
}
}
}
}
}
int main(){
scanf("%d",&N);
pL.read();pR.read();
S.read();T.read();
for(int i = 1;i <= N;++i){
C[i].read();scanf("%lf", r+i);
}
L[++cnt_lines] = Line(S, T);
for(int i = 1;i <= N;++i){
L[++cnt_lines] = tangent(S, C[i], r[i], 1);
L[++cnt_lines] = tangent(S, C[i], r[i], -1);
L[++cnt_lines] = tangent(T, C[i], r[i], 1);
L[++cnt_lines] = tangent(T, C[i], r[i], -1);
}
for(int i = 1;i <= N;++i){
for(int j = i + 1;j <= N;++j){
L[++cnt_lines] = tangent_out(C[i], r[i], C[j], r[j], 1);
L[++cnt_lines] = tangent_out(C[i], r[i], C[j], r[j],-1);
L[++cnt_lines] = tangent_in(C[i], r[i], C[j], r[j], 1);
L[++cnt_lines] = tangent_in(C[i], r[i], C[j], r[j],-1);
}
}
for(int i=1;i<=cnt_lines;++i){
bool flag = true;
for(int j = 1;j <= N;++j){
if(intersect(L[i], C[j], r[j])){
flag = false;break;
}
}
if(flag){
L[++cnt_lines2] = L[i];
}
}
L[++cnt_lines2] = Line(point(pL.x, pL.y), point(pL.x, pR.y), 0, 1);
L[++cnt_lines2] = Line(point(pR.x, pL.y), point(pR.x, pR.y), 0, 1);
L[++cnt_lines2] = Line(point(pL.x, pL.y), point(pR.x, pL.y), 0, 1);
L[++cnt_lines2] = Line(point(pL.x, pR.y), point(pR.x, pR.y), 0, 1);
for(int i=1;i<=cnt_lines2 - 4;++i){
for(int j=cnt_lines2 - 3;j<=cnt_lines2;++j){
point p = intersect(L[i], L[j]);
double t = L[i].gett(p);
if(t<0&&t>L[i].tmin){
L[i].tmin = t;
}
if(t>0&&t<L[i].tmax){
L[i].tmax = t;
}
}
}
bfs();
return 0;
}

Asia Jakarta Regional Contest 2019 I - Mission Possible的更多相关文章

  1. 2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)

    2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred) easy: ACE ...

  2. 2019-2020 ICPC, Asia Jakarta Regional Contest

    目录 Contest Info Solutions A. Copying Homework C. Even Path E. Songwriter G. Performance Review H. Tw ...

  3. 2019-2020 ICPC, Asia Jakarta Regional Contest H. Twin Buildings

    As you might already know, space has always been a problem in ICPC Jakarta. To cope with this, ICPC ...

  4. 2018 ICPC Asia Jakarta Regional Contest

    题目传送门 题号 A B C D E F G H I J K L 状态 Ο . . Ο . . Ø Ø Ø Ø . Ο Ο:当场 Ø:已补 .  :  待补 A. Edit Distance Thin ...

  5. 2019-2020 ICPC, Asia Jakarta Regional Contest C. Even Path

    Pathfinding is a task of finding a route between two points. It often appears in many problems. For ...

  6. 2019-2020 ICPC, Asia Jakarta Regional Contest A. Copying Homework

    Danang and Darto are classmates. They are given homework to create a permutation of N integers from  ...

  7. 模拟赛小结:2019-2020 ICPC, Asia Jakarta Regional Contest

    比赛链接:传送门 离金最近的一次?,lh大佬carry场. Problem A. Copying Homework 00:17(+) Solved by Dancepted 签到,读题有点慢了.而且配 ...

  8. 2016 Asia Jakarta Regional Contest L - Tale of a Happy Man UVALive - 7722

    UVALive - 7722 一定要自己做出来!

  9. 2016 Asia Jakarta Regional Contest A - Confusing Date Format UVALive 7711 【模拟题】

    A - Confusing Date Format 题目大意:就是有六种日期格式,给你一个字符串,判断它能组成多少种可能的日期. 第一次WA是:1.没有判重,2.没有特判题目要求的数据,3.判断天数时 ...

随机推荐

  1. Versioning information could not be retrieved from the NuGet package repository. Please try again later.

    Versioning information could not be retrieved from the NuGet package repository. Please try again la ...

  2. c++11多线程记录5: Unique Lock和延时初始化

    https://www.youtube.com/user/BoQianTheProgrammer 视频网址 Unique Lock unique_lock和lock_guard类似,都是mutex的w ...

  3. cas sso 单点登录

    一些介绍: https://www.jianshu.com/p/b7de8e4cf217 https://blog.csdn.net/javaloveiphone/article/details/52 ...

  4. java之spring mvc之helloworld

    这篇主要讲解springmvc的基本的使用,这里以helloworld项目为例. 目录结构: 1. 新建 web 项目 :springmvc_helloworld 2. 在 WebRoot\WEB-I ...

  5. jquery.pagination.js分页demo

    公用jquery.pagination.js /** * This jQuery plugin displays pagination links inside the selected elemen ...

  6. activiti用户手册

    http://www.mossle.com/docs/activiti/index.html

  7. 有价证券secuerity英语

    证券业 证券业是为证券投资活动服务的专门行业.各国定义的证券业范围略有不同.按照美国的 “产业分类标准”,证券业由证券经纪公司.证券交易所和有关的商品经纪集团组成.证券业在世界各国都是一个小的产业部门 ...

  8. 如何统一管理单个任务下所有API的同步情况?

    如何统一管理单个任务下所有API的同步情况 1. 一分钟完成单个API配置 单个API的配置包含:API名称.URL地址.请求方式.参数设置.自定义高级设置. 参数允许用户填写:Text.WebSer ...

  9. 关于小程序授权地理位置(wx.getLocation + 用户体验)

    wx.getLocation 如果用户曾点击过一次 “确认授权” , 那么再次调用该接口时将不会出现弹出框(可以直接拿到经纬度) 关于用户体验: 在 onLoad 中判断: 如果用户之前“没有触发过“ ...

  10. 实验3 SQL注入原理-万能密码注入

    实验目的 (1)理解[万能密码]的原理 (2)学习[万能密码]的使用 实验原理 一.访问目标网站 1.选择一个存在漏洞的论坛 http://192.168.1.3:8009 进入 2.输入用户名[ad ...