可真是道恶心题……

首先翻译一下6个任务:

  1. 给出一个三角形,求它的外界圆。
  2. 给出一个三角形,求它的内接圆。
  3. 给出一个圆和一个点,求过这个点的切线的倾斜角\(\alpha \in [0,180)\)。(这个点可能在圆内或圆上)
  4. 给出一条切线、圆上一点和圆的半径,求圆心位置。(此问题和后面的问题都可能无解或有多个解)
  5. 给出两条切线和圆的半径,求圆心位置。
  6. 给出两个外切圆和半径,求圆心位置。

若有多个解,从小到大输出答案。(点排序时以\(x\)为第一关键字)

可以发现,上面的问题经过简单的转换后,就是要求我们实现:

  • 求点到直线的距离。
  • 求点在直线上的垂足。
  • 求直线的垂直平分线。
  • 求角的平分线。
  • 求两条直线的交点。
  • 求圆和一条直线的交点。
  • 求两个圆的交点。

然后,我们写\(O(1)\)个小时就能写出来了(大雾

#include <bits/stdc++.h>
using namespace std;
typedef double db;
const db eps = 1e-8, INF = 1.0 / 0.0, pi = acos(-1);
inline int judge(db x) {
return x > -eps ? x > eps ? 1 : 0 : -1;
}
#define NULLP point(INF,INF)
struct point {
db x,y;
point(db x_=0,db y_=0): x(x_), y(y_) {}
db abs() const {
return sqrt(x * x + y * y);
}
db norm() const {
return x * x + y * y;
}
bool operator < (const point& a) const {
return judge(x - a.x) != 0 ? judge(x - a.x) < 0 : judge(y - a.y) < 0;
}
point operator - () const {
return point(-x, -y);
}
point operator * (const db& a) const {
return point(x * a, y * a);
}
point operator / (const db& a) const {
return point(x / a, y / a);
}
point* operator *= (const db& a) {
return *this = *this * a, this;
}
point* operator /= (const db& a) {
return *this = *this / a, this;
}
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);
}
point* operator += (const point& a) {
return *this = *this + a, this;
}
point* operator -= (const point& a) {
return *this = *this - a, this;
}
bool avail() {
return (fabs(x) != INF) && (fabs(y) != INF);
}
};
db dot(point a,point b) {
return a.x * b.x + a.y * b.y;
}
db cross(point a,point b) {
return a.x * b.y - a.y * b.x;
}
point unit(point a) {
db t = a.abs();
if (judge(t) == 0) return a;
return a / t;
}
struct line {
point u,v;
line(point u_=point(),point v_=point()): u(u_) {
v = unit(v_);
}
};
db dist(point u,line l) {
return fabs(cross(u - l.u,l.v));
}
point foot_point(point u,line l) {
return l.u + (l.v * dot(u - l.u,l.v));
}
point perpen(point a) {
return point(a.y, -a.x);
}
point crossover(line a,line b) {
if (judge(cross(a.v,b.v)) == 0) return NULLP;
point f1 = foot_point(b.u,a);
point f2 = foot_point(f1,b);
if (judge(dot(f2 - b.u,b.v)) < 0) b.v = -b.v;
return b.u + b.v * ((f1 - b.u).norm() / (f2 - b.u).abs());
}
line perpen_bi(point a,point b) {
return line((a + b) / 2, perpen(b - a));
}
struct angle {
point o,u,v;
angle(point o_=point(),point u_=point(),point v_=point()): o(o_) {
u = unit(u_);
v = unit(v_);
}
line bise() const {
return line(o,u + v);
}
};
struct circle {
point o;
db r;
circle(point o_=point(),db r_=0): o(o_), r(r_) {}
};
pair<point,point> crossover(circle c,line l) {
point f = foot_point(c.o,l);
db d = dist(c.o,l);
if (judge(d - c.r) > 0) return make_pair(NULLP,NULLP);
if (judge(d - c.r) == 0) return make_pair(f,NULLP);
db t = sqrt(c.r * c.r - d * d);
return make_pair(f + (l.v * t), f - (l.v * t));
}
pair<point,point> crossover(circle c1,circle c2) {
if (judge(c1.r - c2.r) < 0) swap(c1,c2);
db d = (c1.o - c2.o).abs();
if (judge(d - c1.r - c2.r) > 0) return make_pair(NULLP,NULLP);
if (judge(c1.r - c2.r - d) > 0) return make_pair(NULLP,NULLP);
db co = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d * c1.r);
line l = line(c1.o,c2.o - c1.o);
point h = l.u + (l.v * c1.r * co);
line t = line(h,perpen(l.v));
return crossover(c1,t);
}
circle CircumscribedCircle(point a,point b,point c) {
line l1 = perpen_bi(a,b);
line l2 = perpen_bi(b,c);
point o = crossover(l1,l2);
return circle(o,(o - a).abs());
}
circle InscribedCircle(point a,point b,point c) {
angle a1 = angle(a,b - a,c - a);
angle a2 = angle(b,a - b,c - b);
line l1 = a1.bise();
line l2 = a2.bise();
point o = crossover(l1,l2);
return circle(o,dist(o,line(a,b-a)));
}
void TangentLineThroughPoint(circle c,point p) {
db d = (p - c.o).abs();
if (judge(d - c.r) < 0) return (void) (puts("[]"));
if (judge(d - c.r) == 0) {
point t = perpen(p - c.o);
db ret = atan(t.y / t.x) / pi * 180;
if (judge(ret) < 0) ret = ret + 180;
return (void) (printf("[%.6lf]\n",ret));
}
db r = sqrt(d * d - c.r * c.r);
pair<point,point> tmp = crossover(circle(p,r),c);
point t;
db ret1, ret2;
t = tmp.first - p;
ret1 = atan(t.y / t.x) / pi * 180;
if (judge(ret1) < 0) ret1 += 180;
t = tmp.second - p;
ret2 = atan(t.y / t.x) / pi * 180;
if (judge(ret2) < 0) ret2 += 180;
if (judge(ret1 - ret2) > 0) swap(ret1,ret2);
printf("[%.6lf,%.6lf]\n",ret1,ret2);
}
void output(vector<point>& ret) {
sort(ret.begin(),ret.end());
if (ret.size() == 0) return (void) (puts("[]"));
printf("[(%.6lf,%.6lf)",ret[0].x,ret[0].y);
for (int i = 1 ; i < (int)ret.size() ; ++ i)
printf(",(%.6lf,%.6lf)",ret[i].x,ret[i].y);
puts("]");
}
void CircleThroughAPointAndTangentToALineWithRadius(point p,line l,db r) {
static vector<point> ret;
ret.clear();
point t = perpen(l.v);
line l1 = line(l.u + (t * r),l.v);
line l2 = line(l.u - (t * r),l.v);
circle c = circle(p,r);
pair<point,point> tmp;
tmp = crossover(c,l1);
if (tmp.first.avail()) ret.push_back(tmp.first);
if (tmp.second.avail()) ret.push_back(tmp.second);
tmp = crossover(c,l2);
if (tmp.first.avail()) ret.push_back(tmp.first);
if (tmp.second.avail()) ret.push_back(tmp.second);
output(ret);
}
void CircleTangentToTwoLinesWithRadius(line a,line b,db r) {
static vector<point> ret;
ret.clear();
point t;
t = perpen(a.v);
line a1 = line(a.u + (t * r),a.v);
line a2 = line(a.u - (t * r),a.v);
t = perpen(b.v);
line b1 = line(b.u + (t * r),b.v);
line b2 = line(b.u - (t * r),b.v);
t = crossover(a1,b1);
if (t.avail()) ret.push_back(t);
t = crossover(a1,b2);
if (t.avail()) ret.push_back(t);
t = crossover(a2,b1);
if (t.avail()) ret.push_back(t);
t = crossover(a2,b2);
if (t.avail()) ret.push_back(t);
output(ret);
}
void CircleTangentToTwoDisjointCirclesWithRadius(circle c1,circle c2,db r) {
static vector<point> ret;
ret.clear();
c1.r += r;
c2.r += r;
pair<point,point> tmp;
tmp = crossover(c1,c2);
if (tmp.first.avail()) ret.push_back(tmp.first);
if (tmp.second.avail()) ret.push_back(tmp.second);
output(ret);
}
int main() {
string tmp;
point a,b,c,d;
circle cir;
db t,t1,t2;
while (cin >> tmp) {
if (tmp == "CircumscribedCircle") {
scanf("%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y);
cir = CircumscribedCircle(a,b,c);
printf("(%.6lf,%.6lf,%.6lf)\n",cir.o.x,cir.o.y,cir.r);
}
if (tmp == "InscribedCircle") {
scanf("%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y);
cir = InscribedCircle(a,b,c);
printf("(%.6lf,%.6lf,%.6lf)\n",cir.o.x,cir.o.y,cir.r);
}
if (tmp == "TangentLineThroughPoint") {
scanf("%lf%lf%lf%lf%lf",&cir.o.x,&cir.o.y,&cir.r,&a.x,&a.y);
TangentLineThroughPoint(cir,a);
}
if (tmp == "CircleThroughAPointAndTangentToALineWithRadius") {
scanf("%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&t);
CircleThroughAPointAndTangentToALineWithRadius(a,line(b,c - b),t);
}
if (tmp == "CircleTangentToTwoLinesWithRadius") {
scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&d.x,&d.y,&t);
CircleTangentToTwoLinesWithRadius(line(a,b-a),line(c,d-c),t);
}
if (tmp == "CircleTangentToTwoDisjointCirclesWithRadius") {
scanf("%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&t1,&b.x,&b.y,&t2,&t);
CircleTangentToTwoDisjointCirclesWithRadius(circle(a,t1),circle(b,t2),t);
}
}
return 0;
}

小结:我写得太久了。敲键盘时还总是有迟疑。

【做题】UVA-12304——平面计算集合六合一的更多相关文章

  1. 【Leetcode 做题学算法周刊】第六期

    首发于微信公众号<前端成长记>,写于 2019.12.15 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 11 ...

  2. DP【洛谷P1704】 寻找最优美做题曲线

    [洛谷P1704] 寻找最优美做题曲线 题目背景 nodgd是一个喜欢写程序的同学,前不久(好像还是有点久了)洛谷OJ横空出世,nodgd同学当然第一时间来到洛谷OJ刷题.于是发生了一系列有趣的事情, ...

  3. LIS【p1704】寻找最优美做题曲线

    Description 洛谷OJ刷题有个有趣的评测功能,就是系统自动绘制出用户的"做题曲线".所谓做题曲线就是一条曲线,或者说是折线,是这样定义的:假设某用户在第b[i]天AC了c ...

  4. luogu P1704 寻找最优美做题曲线

    题目背景 nodgd是一个喜欢写程序的同学,前不久(好像还是有点久了)洛谷OJ横空出世,nodgd同学当然第一时间来到洛谷OJ刷题.于是发生了一系列有趣的事情,他就打算用这些事情来出题恶心大家-- 题 ...

  5. NOIP2016考前做题(口胡)记录

    NOIP以前可能会持续更新 写在前面 NOIP好像马上就要到了,感觉在校内训练里面经常被虐有一种要滚粗的感觉(雾.不管是普及组还是提高组,我都参加了好几年了,结果一个省一都没有,今年如果还没有的话感觉 ...

  6. CodeM美团点评编程大赛复赛 做题感悟&题解

    [T1] [简要题意]   长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...

  7. SDOI2016 R1做题笔记

    SDOI2016 R1做题笔记 经过很久很久的时间,shzr终于做完了SDOI2016一轮的题目. 其实没想到竟然是2016年的题目先做完,因为14年的六个题很早就做了四个了,但是后两个有点开不动.. ...

  8. AtCoder Grand Contest 11~17 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-11-to-20.html UPD(2018-11-16): ...

  9. AtCoder Grand Contest 1~10 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...

随机推荐

  1. Discuz-阅读权限

    设置用户浏览帖子或附件的权限级别,范围 0-255,0 为禁止用户浏览任何帖子或附件. 当用户的阅读权限小于帖子或附件的阅读权限许可(默认时为 1)时, 用户将不能阅读该帖子或下载该附件

  2. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub

    上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...

  3. Redis 的 5 个常见应用场景

    前言Redis 是一个强大的内存型存储,具有丰富的数据结构,使其可以应用于很多方面,包括作为数据库.缓存.消息队列等等. 如果你的印象中Redis只是一个 key-value 存储,那就错过了Redi ...

  4. ETL面试题集锦

    1. What is a logical data mapping and what does it mean to the ETL team? 什么是逻辑数据映射?它对ETL项目组的作用是什么? 答 ...

  5. Windows 7关闭睡眠(休眠)模式和删除休眠文件

    原文地址:https://www.192ly.com/pc/win7/gb-sm.html 怎么关闭Windows 7关闭睡眠(休眠)功能?Windows 7系统中怎么删除休眠文件?Windows 7 ...

  6. mybatis源码解析5---SqlSession解析

    由之前解析可知,mybatis启动的时候会加载XML配置文件解析生成全局配置对象Configuration对象,SqlSessionFactoryBuilder类会根据Configuration对象创 ...

  7. Lucene 个人领悟 (二)

    想了想,还是继续写吧,因为,太无聊了,媳妇儿也还有半个小时才下班. 前面拖拖拉拉用了三篇文章来做铺垫,这一篇开始正经搞了啊. 首先,我要加几个链接 http://www.cnblogs.com/xin ...

  8. redis安装集群的2种方式

    redis主从只是数据的备份,当主宕机后不会自动切换从为主,需要手动切换从为主. 哨兵就可以自动切换从为主, 当主数据库遇到异常中断服务后,开发者可以通过手动的方式选择一个从数据库来升格为主数据库,以 ...

  9. 案例:配置apache和nginx的SSL加密传输协议

    一.SSI解释 SSI是一种类似于ASP的基于服务器的网页制作技术.将内容发送到浏览器之前,可以使用“服务器端包含 (SSI)”指令将文本.图形或应用程序信息包含到网页中.例如,可以使用 SSI 包含 ...

  10. 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)

    摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...