您的位置:首页 > 其它

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,结果样例有一组相切的过不了。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: