UVA 12304 圆的各种模板混搭题(250行)
2013-09-26 21:41
423 查看
纯手敲,大概花了1小时不到,检查了一会,发现圆和直线交写搓了,改过来以后就AC了。
题意:6种各自独立的询问。
询问1:给你一个三角形,求其外接圆圆心和半径。
询问2:给你一个三角形,求其内接圆圆心和半径
询问3:给你一个圆和一个点,求其所有切线的极角(规范0<=angle < pi)
询问4:给你一个点和一条直线和半径r,求所有满足半径为r且经过该点并与直线相切的圆的圆心
询问5:给你两条不平行的直线和半径r,求所有满足半径为r且与这两直线相切的圆的圆心
询问6:给你两个相离的圆和半径r,求所有满足半径为r且与这两个圆外切的圆的圆心
思路:对于询问1,2可以暴力用线段交算,这样做精度损失很大,考虑到这个情况,我直接套公式了,是解方程得出 来的。
对于询问3,求个圆心与点的连线和切线的角度,很容易得出切线的极角
对于询问4,5,6, 注意只求圆心,半径为r的圆, 对于与其直线相切的其圆心轨迹为2条直线, 经过某一点 圆心轨迹为一个圆(半径r),与圆(半径为w)外切圆心轨迹还是一个圆(半径为r+w)
注意:精度eps 我定为1e-6,我先定了1e-8,结果样例有一组相切的过不了。
题意:6种各自独立的询问。
询问1:给你一个三角形,求其外接圆圆心和半径。
询问2:给你一个三角形,求其内接圆圆心和半径
询问3:给你一个圆和一个点,求其所有切线的极角(规范0<=angle < pi)
询问4:给你一个点和一条直线和半径r,求所有满足半径为r且经过该点并与直线相切的圆的圆心
询问5:给你两条不平行的直线和半径r,求所有满足半径为r且与这两直线相切的圆的圆心
询问6:给你两个相离的圆和半径r,求所有满足半径为r且与这两个圆外切的圆的圆心
思路:对于询问1,2可以暴力用线段交算,这样做精度损失很大,考虑到这个情况,我直接套公式了,是解方程得出 来的。
对于询问3,求个圆心与点的连线和切线的角度,很容易得出切线的极角
对于询问4,5,6, 注意只求圆心,半径为r的圆, 对于与其直线相切的其圆心轨迹为2条直线, 经过某一点 圆心轨迹为一个圆(半径r),与圆(半径为w)外切圆心轨迹还是一个圆(半径为r+w)
注意:精度eps 我定为1e-6,我先定了1e-8,结果样例有一组相切的过不了。
#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <string> #include <iostream> #include <algorithm> using namespace std; const double eps = 1e-6; const double pi = acos(-1.0); int dcmp(double x) { if(fabs(x) < eps) return 0; return x > eps ? 1 : -1; } struct point { double x, y; point(){} point(double x, double y): x(x), y(y) {} point operator+(const point &t) const { return point(x+t.x, y+t.y); } point operator-(const point &t) const { return point(x-t.x, y-t.y); } point operator*(const double &t) const { return point(x*t, y*t); } point operator/(const double &t) const { return point(x/t, y/t); } bool operator<(const point &t) const { return x + eps < t.x || (!dcmp(x-t.x) && y < t.y); } double len() { return sqrt(x*x+y*y); } double len2() { return x*x+y*y; } point normal() { return point(-y, x)/len(); } void in() { scanf("%lf%lf", &x, &y); } void out() { printf("(%.6f,%.6f)", x, y); } }; double dis(point a, point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } point rotate(point a, double ct) { return point(a.x*cos(ct)-a.y*sin(ct), a.y*cos(ct)+a.x*sin(ct)); } double cross(point a, point b) { return a.x*b.y-a.y*b.x; } double dot(point a, point b) { return a.x*b.x+a.y*b.y; } double fix(double x) { if(x < -eps) x += pi; return x*180.0/pi; } double angle(point v) { return atan2(v.y, v.x); } double disPointToLine(point a, point l, point r) { return fabs(cross(a-l, r-l))/dis(l, r); } struct Line { point a, v; void in() { a.in(); v.in(); v = v-a; } Line() {} Line(point a, point v): a(a), v(v) {} }; void lineLineIntersect(Line l, Line r, vector <point> &sol) { double t = cross((r.a-l.a), r.v) / cross(l.v, r.v); sol.push_back(l.a+l.v*t); } struct Circle { point o; double r; void in() { o.in(); scanf("%lf", &r); } point getPoint(double ct) { return point(r*cos(ct), r*sin(ct))+o; } void out() { printf("(%.6f,%.6f,%.6f)\n", o.x, o.y, r); } Circle(point o, double r): o(o), r(r) {} Circle() {} }; void cirLineIntersect(Circle C, Line L, vector <point> &sol) { double e = L.v.len2(), f = dot(L.a-C.o, L.v)*2, g = (L.a-C.o).len2()-C.r*C.r; double dlt = f*f-4*e*g; //printf("dlt = %.10f\n", dlt); if(dlt < -eps) return; if(dlt < eps) { double t = -f/(2*e); sol.push_back(L.v*t+L.a); return; } dlt = sqrt(dlt); double t1 = (-f+dlt)/(2*e), t2 = (-f-dlt)/(2*e); sol.push_back(L.v*t1+L.a); sol.push_back(L.v*t2+L.a); } void cirCirIntersect(Circle C1, Circle C2, vector <point> &sol) { point v = C2.o - C1.o; double d = v.len(); if(dcmp(d-C1.r-C2.r) > 0) return; double ct = angle(v), alf = acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d)); sol.push_back(C1.getPoint(ct+alf)); if(dcmp(alf) > eps)sol.push_back(C1.getPoint(ct-alf)); } Circle CircumscribedCircle(point p1, point p2, point p3) { //one double bx = p2.x-p1.x, by = p2.y-p1.y; double cx = p3.x-p1.x, cy = p3.y-p1.y; double d = 2*(bx*cy-by*cx); double ox = (cy*(bx*bx+by*by) - by*(cx*cx+cy*cy))/d + p1.x; double oy = (bx*(cx*cx+cy*cy) - cx*(bx*bx+by*by))/d + p1.y; point o = point(ox, oy); return Circle(o, dis(o, p1)); } Circle InscribedCircle(point p1, point p2, point p3) { // two double a = dis(p2, p3); double b = dis(p1, p3); double c = dis(p1, p2); point o = (p1*a+p2*b+p3*c)/(a+b+c); return Circle(o, disPointToLine(o, p1, p2)); } vector <double> TangentLineThroughPoint(point p, Circle c) { //three vector <double> sol; point u = c.o - p; double d = u.len(); if(d +eps < c.r) return sol; else if(!dcmp(d-c.r)) { sol.push_back( fix(angle(rotate(u, -pi/2))) ); } else { double alf = asin(c.r/d); sol.push_back( fix(angle(rotate(u, -alf))) ); sol.push_back( fix(angle(rotate(u, +alf))) ); } sort(sol.begin(), sol.end()); return sol; } vector <point> CircleThroughAPointAndTangentToALineWithRadius(point o, Line L, double r) { //four vector <point> sol; point v = L.v.normal(); cirLineIntersect(Circle(o, r), Line(L.a+v*r, L.v), sol); cirLineIntersect(Circle(o, r), Line(L.a-v*r, L.v), sol); sort(sol.begin(), sol.end()); return sol; } vector <point> CircleTangentToTwoLinesWithRadius(Line L1, Line L2, double r) { //five vector <point> sol; point v1 = L1.v.normal(); point v2 = L2.v.normal(); lineLineIntersect(Line(L1.a+v1*r, L1.v), Line(L2.a+v2*r, L2.v), sol); lineLineIntersect(Line(L1.a+v1*r, L1.v), Line(L2.a-v2*r, L2.v), sol); lineLineIntersect(Line(L1.a-v1*r, L1.v), Line(L2.a+v2*r, L2.v), sol); lineLineIntersect(Line(L1.a-v1*r, L1.v), Line(L2.a-v2*r, L2.v), sol); sort(sol.begin(), sol.end()); return sol; } vector <point> CircleTangentToTwoDisjointCirclesWithRadius(Circle C1, Circle C2, double r) { //six vector <point> sol; cirCirIntersect(Circle(C1.o, C1.r+r), Circle(C2.o, C2.r+r), sol); sort(sol.begin(), sol.end()); return sol; } string op; void print(vector <point> sol) { printf("["); for(int i = 0; i < sol.size(); i++) { sol[i].out(); if(i != sol.size()-1) printf(","); } printf("]\n"); } int main() { while(cin >> op) { if(op == "CircumscribedCircle") { point a, b, c; a.in(), b.in(), c.in(); CircumscribedCircle(a, b, c).out(); } else if(op == "InscribedCircle") { point a, b, c; a.in(), b.in(), c.in(); InscribedCircle(a, b, c).out(); } else if(op == "TangentLineThroughPoint") { Circle c; point p; c.in(); p.in(); vector <double> ans = TangentLineThroughPoint(p, c); printf("["); for(int i = 0; i < ans.size(); i++) { printf("%.6f", ans[i]); if(i != ans.size()-1) printf(","); } printf("]\n"); } else if(op == "CircleThroughAPointAndTangentToALineWithRadius") { point p; Line l; double r; p.in(), l.in(), scanf("%lf", &r); print(CircleThroughAPointAndTangentToALineWithRadius(p, l, r)); } else if(op == "CircleTangentToTwoLinesWithRadius") { Line L1, L2; double r; L1.in(); L2.in(); scanf("%lf", &r); print(CircleTangentToTwoLinesWithRadius(L1, L2, r)); } else if(op == "CircleTangentToTwoDisjointCirclesWithRadius") { Circle c1, c2; double r; c1.in(); c2.in(); scanf("%lf", &r); print(CircleTangentToTwoDisjointCirclesWithRadius(c1, c2, r)); } } return 0; }
相关文章推荐
- java反射机制个人学习笔记
- servlet下载,解决文件名中有中文下载路径出现乱码不能正常下载问题
- django: startproject
- magento 修改 paypal order product name
- 整型数组处理算法(二)文件中有一组整数,要求排序后输出到另一个文件中
- N小时改变一次url时间戳的方法
- 《UNIX环境高级编程》笔记--chown,fchown和lchown函数
- 解决一个maven在eclipse中M2_HOME不能调整的问题
- c++动态联编与静态联编
- 单源最短路径—Bellman-Ford和Dijkstra算法
- 如何禁用注册表 解禁注册表
- Fx Composer2.5 在Win8.1下无法运行的解决方法
- 硬盘“坏了”怎么办
- Mex
- php文件操作及html生成
- 关于PHP页面显示乱码问题的解决
- 关于 lighttpd 和它的流行看出 开源社区是如何的不严谨
- 上传文件
- 分页管理
- PHP+MYSQL 简单的留言板