UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!
这个题能1A纯属运气,要是WA掉,可真不知道该怎么去调了。
题意:
这是完全独立的6个子问题。代码中是根据字符串的长度来区分问题编号的。
- 给出三角形三点坐标,求外接圆圆心和半径。
- 给出三角形三点坐标,求内切圆圆心和半径。
- 给出一个圆和一个定点,求过定点作圆的所有切线的倾角(0≤a<180°)
- 给出一个点和一条直线,求一个半径为r的过该点且与该直线相切的圆。
- 给出两条相交直线,求所有半径为r且与两直线都相切的圆。
- 给出两个相离的圆,求半径为r且与两圆都相切的圆。
分析:
- 写出三角形两边的垂直平分线的一般方程(注意去掉分母,避免直线是水平或垂直的特殊情况),然后联立求解即可。
- 有一个很简洁的三角形内心坐标公式(证明有点复杂,可用向量来证,其中多次用到角平分线定理),公式详见代码。
- 分点在圆内,圆上,圆外三种情况,注意最终结果的范围。
- 到定点距离为r的轨迹是个圆,与直线相切的圆心的轨迹是两条平行直线。最终转化为求圆与两条平行线的交点。
- 我开始用的方法是求出圆心到两直线交点的距离,以及与其中一条直线的夹角,依次旋转三个90°即可得到另外三个点。但是对比正确结果,误差居然达到了个位(如果代码没有错的话)!后来参考了lrj的思路,就是讲两直线分别向两侧平移r距离,这样得到的四条直线两两相交得到的四个交点就是所求。
- 看起来有点复杂,仔细分析,半径为r与圆外切的圆心的轨迹还是个圆。因此问题转化为求半径扩大以后的两圆的交点。
体会:
- (Point)(x, y)是强制类型转换,Point(x, y)才是调用构造函数。前者只会将x的值复制,y的值则是默认值0.
- 计算的中间步骤越多,误差越大,最好能优化算法,或者调整EPS的大小。
- //#define LOCAL
- #include <cstdio>
- #include <cstring>
- #include <string>
- #include <algorithm>
- #include <cmath>
- #include <vector>
- using namespace std;
- struct Point
- {
- double x, y;
- Point(double xx=, double yy=) :x(xx),y(yy) {}
- };
- typedef Point Vector;
- Point read_point(void)
- {
- double x, y;
- scanf("%lf%lf", &x, &y);
- return Point(x, y);
- }
- const double EPS = 1e-;
- const double PI = acos(-1.0);
- Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
- Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }
- Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
- Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
- bool operator < (const Point& a, const Point& b)
- { return a.x < b.x || (a.x == b.x && a.y < b.y); }
- int dcmp(double x)
- { if(fabs(x) < EPS) return ; else return x < ? - : ; }
- bool operator == (const Point& a, const Point& b)
- { return dcmp(a.x-b.x) == && dcmp(a.y-b.y) == ; }
- double Dot(Vector A, Vector B)
- { return A.x*B.x + A.y*B.y; }
- double Length(Vector A) { return sqrt(Dot(A, A)); }
- double Angle(Vector A, Vector B)
- { return acos(Dot(A, B) / Length(A) / Length(B)); }
- double Angle2(Vector A) { return atan2(A.y, A.x); }
- Vector VRotate(Vector A, double rad)
- {
- return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
- }
- Vector Normal(Vector A)
- {
- double l = Length(A);
- return Vector(-A.y/l, A.x/l);
- }
- double Change(double r) { return r / PI * 180.0; }
- double Cross(Vector A, Vector B)
- { return A.x*B.y - A.y*B.x; }
- struct Circle
- {
- double x, y, r;
- Circle(double x=, double y=, double r=):x(x), y(y), r(r) {}
- Point point(double a)
- {
- return Point(x+r*cos(a), y+r*sin(a));
- }
- };
- const int maxn = ;
- char s[maxn];
- int ID(char* s)
- {
- int l = strlen(s);
- switch(l)
- {
- case : return ;
- case : return ;
- case : return ;
- case : return ;
- case : return ;
- case : return ;
- default: return -;
- }
- }
- void Solve(double A1, double B1, double C1, double A2, double B2, double C2, double& ansx, double& ansy)
- {
- ansx = (B1*C2 - B2*C1) / (A1*B2 - A2*B1);
- ansy = (C2*A1 - C1*A2) / (B1*A2 - B2*A1);
- }
- void problem0()
- {
- Point A, B, C;
- scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y);
- double A1 = B.x-A.x, B1 = B.y-A.y, C1 = (A.x*A.x-B.x*B.x+A.y*A.y-B.y*B.y)/;
- double A2 = C.x-A.x, B2 = C.y-A.y, C2 = (A.x*A.x-C.x*C.x+A.y*A.y-C.y*C.y)/;
- Point ans;
- Solve(A1, B1, C1, A2, B2, C2, ans.x, ans.y);
- double r = Length(ans - A);
- printf("(%.6lf,%.6lf,%.6lf)\n", ans.x, ans.y, r);
- }
- void problem1()
- {
- Point A, B, C;
- scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y);
- double a = Length(B-C), b = Length(A-C), c = Length(A-B);
- double l = a+b+c;
- Point ans = (A*a+B*b+C*c)/l;
- double r = fabs(Cross(A-B, C-B)) / l;
- printf("(%.6lf,%.6lf,%.6lf)\n", ans.x, ans.y, r);
- }
- void problem2()
- {
- Circle C;
- Point P, O;
- scanf("%lf%lf%lf%lf%lf", &C.x, &C.y, &C.r, &P.x, &P.y);
- double ans[];
- O.x = C.x, O.y = C.y;
- double d = Length(P-O);
- int k = dcmp(d-C.r);
- if(k < )
- {
- printf("[]\n");
- return;
- }
- else if(k == )
- {
- ans[] = Change(Angle2(P-O)) + 90.0;
- while(ans[] >= 180.0) ans[] -= 180.0;
- while(ans[] < ) ans[] += 180.0;
- printf("[%.6lf]\n", ans[]);
- return;
- }
- else
- {
- double ag = asin(C.r/d);
- double base = Angle2(P-O);
- ans[] = base + ag, ans[] = base - ag;
- ans[] = Change(ans[]), ans[] = Change(ans[]);
- while(ans[] >= 180.0) ans[] -= 180.0;
- while(ans[] < ) ans[] += 180.0;
- while(ans[] >= 180.0) ans[] -= 180.0;
- while(ans[] < ) ans[] += 180.0;
- if(ans[] >= ans[]) swap(ans[], ans[]);
- printf("[%.6lf,%.6lf]\n", ans[], ans[]);
- }
- }
- vector<Point> sol;
- struct Line
- {
- Point p;
- Vector v;
- Line() { }
- Line(Point p, Vector v): p(p), v(v) {}
- Point point(double t)
- {
- return p + v*t;
- }
- Line move(double d)
- {
- return Line(p + Normal(v)*d, v);
- }
- };
- Point GetIntersection(Line a, Line b)
- {
- Vector u = a.p - b.p;
- double t = Cross(b.v, u) / Cross(a.v, b.v);
- return a.p + a.v*t;
- }
- struct Circle2
- {
- Point c; //圆心
- double r; //åŠå¾„
- Point point(double a)
- {
- return Point(c.x+r*cos(a), c.y+r*sin(a));
- }
- };
- //两圆相交并返回交点个数
- int getLineCircleIntersection(Line L, Circle2 C, vector<Point>& sol)
- {
- double t1, t2;
- double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
- double e = a*a + c*c, f = *(a*b + c*d), g = b*b + d*d - C.r*C.r;
- double delta = f*f - *e*g; //判别å¼
- if(dcmp(delta) < ) return ; //相离
- if(dcmp(delta) == ) //相切
- {
- t1 = t2 = -f / ( * e);
- sol.push_back(L.point(t1));
- return ;
- }
- //相交
- t1 = (-f - sqrt(delta)) / ( * e); sol.push_back(L.point(t1));
- t2 = (-f + sqrt(delta)) / ( * e); sol.push_back(L.point(t2));
- return ;
- }
- void problem3()
- {
- Circle2 C;
- Point A, B;
- scanf("%lf%lf%lf%lf%lf%lf%lf", &C.c.x, &C.c.y, &A.x, &A.y, &B.x, &B.y, &C.r);
- Vector v = (A-B)/Length(A-B)*C.r;
- //printf("%lf\n", Length(v));
- Point p1 = A + Point(-v.y, v.x);
- Point p2 = A + Point(v.y, -v.x);
- //printf("%lf\n%lf", Length(p1-C.c), Length(p2-C.c));
- Line L1(p1, v), L2(p2, v);
- sol.clear();
- int cnt = getLineCircleIntersection(L1, C, sol);
- cnt += getLineCircleIntersection(L2, C, sol);
- sort(sol.begin(), sol.end());
- if(cnt == ) { printf("[]\n"); return; }
- printf("[");
- for(int i = ; i < cnt-; ++i) printf("(%.6lf,%.6lf),", sol[i].x, sol[i].y);
- printf("(%.6lf,%.6lf)]\n", sol[cnt-].x, sol[cnt-].y);
- }
- void problem4()
- {
- double r;
- Point A, B, C, D, E, ans[];
- 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, &r);
- Line a(A, B-A), b(C, D-C);
- Line L1 = a.move(r), L2 = a.move(-r);
- Line L3 = b.move(r), L4 = b.move(-r);
- ans[] = GetIntersection(L1, L3);
- ans[] = GetIntersection(L1, L4);
- ans[] = GetIntersection(L2, L3);
- ans[] = GetIntersection(L2, L4);
- sort(ans, ans+);
- printf("[");
- for(int i = ; i < ; ++i) printf("(%.6lf,%.6lf),", ans[i].x, ans[i].y);
- printf("(%.6lf,%.6lf)]\n", ans[].x, ans[].y);
- }
- int getCircleCircleIntersection(Circle2 C1, Circle2 C2, vector<Point>& sol)
- {
- double d = Length(C1.c - C2.c);
- if(dcmp(d) == )
- {
- if(dcmp(C1.r - C2.r) == ) return -;
- return ;
- }
- if(dcmp(C1.r + C2.r - d) < ) return ;
- if(dcmp(fabs(C1.r - C2.r) - d) > ) return ;
- double a = Angle2(C2.c - C1.c);
- double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (*C1.r*d));
- Point p1 = C1.point(a+da), p2 = C1.point(a-da);
- sol.push_back(p1);
- if(p1 == p2) return ;
- sol.push_back(p2);
- return ;
- }
- void problem5()
- {
- Circle2 C1, C2;
- double r;
- vector<Point> sol;
- scanf("%lf%lf%lf%lf%lf%lf%lf", &C1.c.x, &C1.c.y, &C1.r, &C2.c.x, &C2.c.y, &C2.r, &r);
- double d = Length(C1.c - C2.c);
- C1.r += r, C2.r += r;
- if(dcmp(C1.r+C2.r-d) < ) { printf("[]\n"); return; }
- int n = getCircleCircleIntersection(C1, C2, sol);
- sort(sol.begin(), sol.end());
- printf("[");
- for(int i = ; i < n-; ++i) printf("(%.6lf,%.6lf),", sol[i].x, sol[i].y);
- printf("(%.6lf,%.6lf)]\n", sol[n-].x, sol[n-].y);
- }
- int main()
- {
- #ifdef LOCAL
- freopen("12304in.txt", "r", stdin);
- #endif
- while(scanf("%s", s) == )
- {
- int proID = ID(s);
- switch(proID)
- {
- case : problem0(); break;
- case : problem1(); break;
- case : problem2(); break;
- case : problem3(); break;
- case : problem4(); break;
- case : problem5(); break;
- default: break;
- }
- }
- return ;
- }
代码君
UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!的更多相关文章
- Uva 12304 - 2D Geometry 110 in 1!
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- 二维剪板机下料问题(2-D Guillotine Cutting Stock Problem) 的混合整数规划精确求解——数学规划的计算智能特征
二维剪板机下料问题(2-D Guillotine Cutting Stock Problem) 的混合整数规划精确求解——数学规划的计算智能特征 二维剪板机下料(2D-GCSP) 的混合整数规划是最优 ...
- UVA 11297 Census(二维线段树)
Description This year, there have been many problems with population calculations, since in some cit ...
- UVA - 11019 Matrix Matcher (二维字符串哈希)
给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数. 看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希. 类比一维情况下的哈希算法,利用容斥 ...
- UVA 10652 Board Wrapping(二维凸包)
传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...
- UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...
- UDF——处理二维网格的利器:Boost.Geometry库
本文编译工具:VC++ UDF Studio 该插件可以直接在Visual Studio中一键编译.加载.调试UDF源码,极大提高编写排错效率,且支持C++,MFC,Windows API和第三方库, ...
- LeetCode 240. 搜索二维矩阵 II(Search a 2D Matrix II) 37
240. 搜索二维矩阵 II 240. Search a 2D Matrix II 题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target.该矩阵具有以下特性 ...
- uva 11178二维几何(点与直线、点积叉积)
Problem D Morley’s Theorem Input: Standard Input Output: Standard Output Morley’s theorem states tha ...
随机推荐
- bnuoj 4209 Triangle(计算几何)
http://www.bnuoj.com/bnuoj/problem_show.php?pid=4209 题意:如题 题解:公式直接计算,或者角平分线求交点 [code1]: #include < ...
- wap开发使用jquery mobile之后页面不加载外部css样式文件/js文件
场景: wap开发,使用jquery mobile之后不会加载外部自定义的css文件了,需要手动刷新才会加载,查看外部自定义的js文件也是一样. 解决办法: 1.在page下面添加css样式,就不要写 ...
- 模仿易信的UI
易信,它的UI还是很简洁,因此本人想模仿一下它,用了一天的时候来研究它的资源文件,终于被我写出来.先看下效果图吧. (一)首页的标题 main_title.xml <?xml v ...
- 送给那些喜欢myeclipse黑色主题但是又不知道怎么配色的人
设置MyEclipse黑色主题背景 1. 下载 http://eclipsecolorthemes.org/ 看哪个合适直接点击进入, 下载右边的epf 2. 下载完成...打开myeclipse. ...
- Python的map、filter、reduce函数 [转]
1. map函数func作用于给定序列的每个元素,并用一个列表来提供返回值. map函数python实现代码: def map(func,seq): mapped_seq = [] fo ...
- ORA-00257: 归档程序错误。在释放之前仅限于内部连接
今天发现oracle数据库连不上,报错:ORA-00257: 归档程序错误.在释放之前仅限于内部连接 马上联想到可能是空间满了,一看磁盘目录,果然. 解决方法如下: 1:查看归档日志目录. 登陆账号后 ...
- sqlserver 类似oracle的rownum功能: row_number
select row_number() over(order by t.id ) as num,id,name from (SELECT distinct [列 0] as id ,[列 1] as ...
- 3243: [Noi2013]向量内积 - BZOJ
Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知 ...
- SUID ,SGID ,Sticky
SUID passwd:s SUID: 运行某程序时,相应进程的属主是程序文件自身的属主,而不是启动者: chmod u+s FILE chmod u-s FILE 如果FILE本身原来就有执行权限, ...
- SVN--从本地检出项目至服务器报错--禁止访问
错误描述: 原因:这是访问权限限制引起的. 查看/svn/test目录的权限--之前我修改过的 现在添加一个user就好了--这个添加的developer是我之前导入本地项目时已经验证过的,所以再导入 ...