UVa12304(计算几何中圆的基本操作)
断断续续写了250多行的模拟,其间被其他事情打扰,总共花了一天才AC吧~
这道题目再次让我明白,有些事情看起来很难,实际上并没有我们想象中的那么难。当然了我主要指的不是这个题的难度……
也是初学计算几何,然后居然胆大妄为地不用刘汝佳的思路去实现这些个功能,其中有三个功能是我用自己的思路实现的吧(瞎暴力),最后果然也是自己写的出锅了。
当一个贼长的模拟题交上去一发WA时,我是欲哭无泪的……这让我怎么debug……只好不断安慰自己要用计算几何题去练习耐心。
只是没想到在不断的固执与冷静的试探之下,不到一个晚上就成功了,当然了,对拍拍出来的呗……
我的主要错误在于在我自己的实现思路里,旋转向量时应该顺时针还是逆时针是取决于输入的,而我粗暴地“一视同仁”了。还好后来发现不难改,加个正负1去control就好了~
自己的辣鸡代码贴一贴留着自己看,难得写这么长:
#include <bits/stdc++.h>
using namespace std; struct Point
{
double x, y;
Point(double a = , double b = ):x(a), y(b){ }
};
typedef Point Vector; const double PI = acos(-1.0);
int dcmp(double x)
{
if (fabs(x) < 1e-) return ;
else return x < ? - : ;
}
Vector operator + (const Point &A, const Point &B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (const Point &A, const Point &B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (const Point &A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator / (const Point &A, double p) { return Vector(A.x / p, A.y / p); }
bool operator < (const Point &A, const Point &B) { return dcmp(A.x - B.x) < || (dcmp(A.x - B.x) == && dcmp(A.y - B.y) < ); }
bool operator == (const Point &A, const Point &B) { return dcmp(A.x - B.x) == && dcmp(A.y - B.y) == ; } double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }
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)); }
Vector Normal(Vector A) { double L = Length(A); return Vector(-A.y / L, A.x / L); }
Vector Rotate(Vector A, double rad) { return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); } Point Get_Line_Intersect(Point P, Vector v, Point Q, Vector w)
{
Point u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v*t;
} double Distance_to_Line(Point P, Point A, Point B)
{
Vector v1 = P - A, v2 = B - A;
return fabs(Cross(v1, v2) / Length(v2));
} struct Circle
{
Point c;
double r;
// Circle(Point a = (0, 0), double x = 0):c(a), r(x){}
Point point(double seta) { return Point(c.x + cos(seta)*r, c.y + sin(seta)*r); }
}; struct Line
{
Point p;
Vector v;
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); }
}; double formattedAngle(Vector A)
{
double a = atan2(A.y, A.x) / PI * ;
if (dcmp(a) < ) a += ;
if (dcmp(a - ) >= ) a -= ;
return a;
} int getTangents(Point P, Circle C, vector<double> &v)
{
Vector u = C.c - P;
double d = Length(u); if (dcmp(d - C.r) < ) return ;
else if (dcmp(d - C.r) == )
{
v.push_back(formattedAngle(Rotate(u, PI/)));
return ;
}
else
{
double a = asin(C.r / d);
v.push_back(formattedAngle(Rotate(u, a)));
v.push_back(formattedAngle(Rotate(u, -a)));
return ;
}
} void get_Line_Circle_Intersection(Line L, Circle C, vector<Point> &ans)
{
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;
else if (dcmp(delta) == )
{
t1 = t2 = -f//e;
ans.push_back(L.point(t1));
}
else
{
t1 = (-f + sqrt(delta)) / / e;
t2 = (-f - sqrt(delta)) / / e;
ans.push_back(L.point(t1)), ans.push_back(L.point(t2));
}
} inline double angle(Vector A) { return atan2(A.y, A.x); } int get_Circle_Circle_Intersection(Circle C1, Circle C2, vector<Point> &v)
{
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 = angle(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); v.push_back(p1);
if (p1 == p2) return ;
v.push_back(p2);
return ;
} void CircumscribedCircle()
{
Point P[];
for (int i = ; i < ; i++) scanf("%lf%lf", &P[i].x, &P[i].y); Point c = Get_Line_Intersect((P[] + P[])/, Rotate(P[] - P[], PI/), (P[] + P[])/, Rotate(P[] - P[], -PI/)); printf("(%.6lf,%.6lf,%.6lf)\n", c.x, c.y, Length(c - P[]));
} void InscribedCircle()
{
Point P[];
for (int i = ; i < ; i++) scanf("%lf%lf", &P[i].x, &P[i].y); Vector v1 = Rotate(P[] - P[], (Cross(P[] - P[], P[] - P[]) > ? - : ) * Angle(P[]-P[], P[]-P[]) / );
Vector v2 = Rotate(P[] - P[], (Cross(P[] - P[], P[] - P[]) > ? - : ) * Angle(P[]-P[], P[]-P[]) / );
Point c = Get_Line_Intersect(P[], v1, P[], v2); printf("(%.6lf,%.6lf,%.6lf)\n", c.x, c.y, Distance_to_Line(c, P[], P[]));
} void TangentLineThroughPoint()
{
Circle C;
Point P;
vector<double> v;
scanf("%lf%lf%lf", &C.c.x, &C.c.y, &C.r);
scanf("%lf%lf", &P.x, &P.y); printf("[");
if (getTangents(P, C, v)) sort(v.begin(), v.end()), printf("%.6lf", v[]);
if (v.size() == ) printf(",%.6lf", v[]);
printf("]\n");
} void CircleThroughAPointAndTangentToALineWithRadius()
{
Circle P;
Point A, B;
scanf("%lf%lf%lf%lf%lf%lf%lf", &P.c.x, &P.c.y, &A.x, &A.y, &B.x, &B.y, &P.r); Line original(A, B - A);
vector<Point> v;
get_Line_Circle_Intersection(original.move(P.r), P, v);
get_Line_Circle_Intersection(original.move(-P.r), P, v);
sort(v.begin(), v.end()); printf("[");
if (v.size()) printf("(%.6lf,%.6lf)", v[].x, v[].y);
for (int i = ; i < v.size(); i++) printf(",(%.6lf,%.6lf)", v[i].x, v[i].y);
printf("]\n");
} inline Point e_to_go(Vector A, double len) { return A / Length(A) * len; } void CircleTangentToTwoLinesWithRadius()
{
Point A, B, C ,D;
double r;
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); vector<Point> v;
int control = Cross(B - A, D - C) < ? - : ; Point P = Get_Line_Intersect(A, B-A, C, D-C);
double seta = Angle(B - A, D - C)/;
Vector v1 = Rotate(B - A, control*seta);
Vector v2 = Rotate(B - A, -control*(PI/ - seta)); v.push_back(P + e_to_go(v1, r/sin(seta)));
v.push_back(P - e_to_go(v1, r/sin(seta)));
v.push_back(P + e_to_go(v2, r/cos(seta)));
v.push_back(P - e_to_go(v2, r/cos(seta)));
sort(v.begin(), v.end()); for (int i = ; i < v.size(); i++)
printf("%c(%.6lf,%.6lf)", ",["[i == ], v[i].x, v[i].y);
printf("]\n");
} void CircleTangentToTwoDisjointCirclesWithRadius()
{
Circle C1, C2;
double r;
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);
C1.r += r, C2.r += r;
vector<Point> v;
get_Circle_Circle_Intersection(C1, C2, v);
sort(v.begin(), v.end()); if (!v.size()) printf("[");
for (int i = ; i < v.size(); i++)
printf("%c(%.6lf,%.6lf)", ",["[i == ], v[i].x, v[i].y);
printf("]\n");
} int main()
{
string s;
while (cin >> s)
{
if (s.length() < ) InscribedCircle();
else
{
switch(s[])
{
case 'e':
CircumscribedCircle(); break;
case 'P':
TangentLineThroughPoint(); break;
case 't':
CircleThroughAPointAndTangentToALineWithRadius(); break;
case 'L':
CircleTangentToTwoLinesWithRadius(); break;
case 'D':
CircleTangentToTwoDisjointCirclesWithRadius(); break;
default : break;
}
}
}
return ;
}
UVa12304(计算几何中圆的基本操作)的更多相关文章
- Oracle中的一些基本操作
关于Oracle中的一些基本操作,包括表空间操作,用户操作,表操作 --创建表空间 create tablespace itheima datafile 'I:\oracle\table\itheim ...
- MATLAB中图像的基本操作
MATLAB中图像的基本操作 1.读取.显示图片 MATLAB中提供了immread()与imshow()函数读取和显示图片.其中读取函数imread()原型: imread: A = imread( ...
- UVA-12304 2D Geometry 110 in 1! (有关圆的基本操作)
UVA-12304 2D Geometry 110 in 1! 该问题包含以下几个子问题 CircumscribedCircle x1 y1 x2 y2 x3 y3 : 三角形外接圆 Inscribe ...
- ACM 计算几何中的精度问题(转)
http://www.cnblogs.com/acsmile/archive/2011/05/09/2040918.html 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模 ...
- C++中map的基本操作和使用;
注:本文来自sina live 的博文 Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作!1. map最基本 ...
- C#中Linq查询基本操作
摘要:本文介绍Linq查询基本操作(查询关键字) - from 子句 - where 子句 - select子句 - group 子句 - into 子句 - orderby 子句 - join 子句 ...
- cocos2d-x3.2中map的基本操作和使用
在游戏开发中,我们有时候会用到map,而map的使用方法我简单给大家介绍一下.Map是c++的一个标准容器,她提供了非常好一对一的关系,在一些程序中建立一个map能够起到事半功倍的效果,总结了一些ma ...
- octave中的一些基本操作
1.矩阵的表示:v = [1 2 2] %表示1行3列的矩阵 v = [1; 2; 2] %表示3行1列的矩阵 v = [1 2; 2 3; 4 5] %3*2矩阵 size(v) % 求v的行与列 ...
- C++使用: C++中map的基本操作和用法
在阅读SSD代码中发现作者使用了C++中的map方法,因此搜索该关联式容器的使用方法,在这里一并总结. 一.Map 簡介 Map是STL的一個容器,它提供一對一的hash. 第一個可以稱為關鍵字(ke ...
随机推荐
- seventBus(封装) 一个巧妙的解决vue同级组件通讯的思路
如果在你项目中需要多处用到同级组件通讯,而又不想去写繁琐的vuex,可以参考这个小思路.本人在写项目中琢磨出来的,感觉挺好用,分享一下. 1.在utils文件夹下添加BusEvent.js 注释已经很 ...
- 关于VLOOKUP函数的用法
“Lookup”的汉语意思是“查找”,在Excel中与“Lookup”相关的函数有三个:VLOOKUP.HLOOKUO和LOOKUP.下面介绍VLOOKUP函数的用法. 一.功能 在表格的首列查找指定 ...
- 关于Ajax实现的简单示例
一.代码示例 关于Ajax的基本概念(包括XMLHttpRequest对象及其相关方法属性)移步这里(w3school中文版)学习了解. <!doctype html> <html ...
- error MSB6006: “CL.exe”已退出,代码为 -1073741502。
错误1error MSB6006: “CL.exe”已退出,代码为 -1073741502.C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Plat ...
- requireJS 加载css、less文件
-- requireJS 同样可以加载css 文件,有require-css的插件,只需要把插件放入main.js同文件夹,在依赖处 采用 ‘css! test.css’的形式就可以加载css文件 - ...
- C语言中文件操作
用两个指针变量来操作字符串. 多维数组在做函数参数的时候,会退化成为一个指针变量,变成一个指向一维数组的数组指针,注意,是一个指针变量. 一维数组在当作函数参数传递的时候,会退化成为一个对应类型的指针 ...
- Oracle中的关键字
NVL和COALESCE的区别: nvl(COMMISSION_PCT,0)如果第一个参数为null,则返回第二个参数如果第一个参数为非null,则返回第一个参数 COALESCE(EXPR1,EXP ...
- 5.oracle中一个字段中存储'a','b'与'a'与a的写法,存储过程中与之对应
select '''a'',''b''' from dual; --'a','b' select '''a''' from dual; --'a' select 'a' from dual; --a
- Excel的poi缓存问题
Excel的poi缓存问题 背景: 最近工作需要,需要完成生成新的Excel,然后从Excel中读取包含公式的文本内容. 问题: 当程序中修改公式对应的单元格数据变化时,公式获取的值仍然还是原来的值, ...
- c/c++面试23-29
23 一般引用的用法 (1)代码 #include <iostream> #include <string> using namespace std; int main(int ...