• UVa12304(计算几何中圆的基本操作)


    断断续续写了250多行的模拟,其间被其他事情打扰,总共花了一天才AC吧~

    这道题目再次让我明白,有些事情看起来很难,实际上并没有我们想象中的那么难。当然了我主要指的不是这个题的难度……

    也是初学计算几何,然后居然胆大妄为地不用刘汝佳的思路去实现这些个功能,其中有三个功能是我用自己的思路实现的吧(瞎暴力),最后果然也是自己写的出锅了。

    当一个贼长的模拟题交上去一发WA时,我是欲哭无泪的……这让我怎么debug……只好不断安慰自己要用计算几何题去练习耐心。

    只是没想到在不断的固执与冷静的试探之下,不到一个晚上就成功了,当然了,对拍拍出来的呗……

    我的主要错误在于在我自己的实现思路里,旋转向量时应该顺时针还是逆时针是取决于输入的,而我粗暴地“一视同仁”了。还好后来发现不难改,加个正负1去control就好了~

    自己的辣鸡代码贴一贴留着自己看,难得写这么长:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 struct Point
      5 {
      6     double x, y;
      7     Point(double a = 0, double b = 0):x(a), y(b){ }
      8 };
      9 typedef Point Vector;
     10 
     11 const double PI = acos(-1.0);
     12 int dcmp(double x)
     13 {
     14     if (fabs(x) < 1e-6)    return 0;
     15     else    return x < 0 ? -1 : 1;
     16 }
     17 Vector operator + (const Point &A, const Point &B) { return Vector(A.x + B.x, A.y + B.y); }
     18 Vector operator - (const Point &A, const Point &B) { return Vector(A.x - B.x, A.y - B.y); }
     19 Vector operator * (const Point &A, double p) { return Vector(A.x * p, A.y * p); }
     20 Vector operator / (const Point &A, double p) { return Vector(A.x / p, A.y / p); }
     21 bool operator < (const Point &A, const Point &B) { return dcmp(A.x - B.x) < 0 || (dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) < 0); }
     22 bool operator == (const Point &A, const Point &B) { return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; }
     23 
     24 double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }
     25 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }
     26 double Length(Vector A) { return sqrt(Dot(A, A)); }
     27 double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }
     28 Vector Normal(Vector A) { double L = Length(A); return Vector(-A.y / L, A.x / L); }
     29 Vector Rotate(Vector A, double rad) { return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); }
     30 
     31 Point Get_Line_Intersect(Point P, Vector v, Point Q, Vector w)
     32 {
     33     Point u = P - Q;
     34     double t = Cross(w, u) / Cross(v, w);
     35     return P + v*t;
     36 }
     37 
     38 double Distance_to_Line(Point P, Point A, Point B)
     39 {
     40     Vector v1 = P - A, v2 = B - A;
     41     return fabs(Cross(v1, v2) / Length(v2));
     42 }
     43 
     44 struct Circle
     45 {
     46     Point c;
     47     double r;
     48     // Circle(Point a = (0, 0), double x = 0):c(a), r(x){}
     49     Point point(double seta) { return Point(c.x + cos(seta)*r, c.y + sin(seta)*r); }
     50 };
     51 
     52 struct Line
     53 {
     54     Point p;
     55     Vector v;
     56     Line(Point p, Vector v):p(p), v(v) { }
     57 
     58     Point point(double t) { return p + v*t; }
     59     Line move(double d) { return Line(p + Normal(v)*d, v); }
     60 };
     61 
     62 double formattedAngle(Vector A)
     63 { 
     64     double a = atan2(A.y, A.x) / PI * 180; 
     65     if (dcmp(a) < 0)    a += 180;
     66     if (dcmp(a - 180) >= 0)    a -= 180;    
     67     return a;
     68 }
     69 
     70 int getTangents(Point P, Circle C, vector<double> &v)
     71 {
     72     Vector u = C.c - P;
     73     double d = Length(u);
     74 
     75     if (dcmp(d - C.r) < 0)    return 0;
     76     else if (dcmp(d - C.r) == 0)
     77     {
     78         v.push_back(formattedAngle(Rotate(u, PI/2)));
     79         return 1;
     80     }
     81     else
     82     {
     83         double a = asin(C.r / d);
     84         v.push_back(formattedAngle(Rotate(u, a)));
     85         v.push_back(formattedAngle(Rotate(u, -a)));
     86         return 2;
     87     }
     88 }
     89 
     90 void get_Line_Circle_Intersection(Line L, Circle C, vector<Point> &ans)
     91 {
     92     double t1, t2;
     93     double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
     94     double e = a*a + c*c, f = 2*(a*b + c*d), g = b*b + d*d - C.r*C.r;
     95     double delta = f*f - 4*e*g;
     96     
     97     if (dcmp(delta) < 0)    return;
     98     else if (dcmp(delta) == 0)
     99     {
    100         t1 = t2 = -f/2/e;
    101         ans.push_back(L.point(t1));
    102     }
    103     else
    104     {
    105         t1 = (-f + sqrt(delta)) / 2 / e;
    106         t2 = (-f - sqrt(delta)) / 2 / e;
    107         ans.push_back(L.point(t1)), ans.push_back(L.point(t2));
    108     }
    109 }
    110 
    111 inline double angle(Vector A) { return atan2(A.y, A.x); }
    112 
    113 int get_Circle_Circle_Intersection(Circle C1, Circle C2, vector<Point> &v)
    114 {
    115     double d = Length(C1.c - C2.c);
    116     if (dcmp(d) == 0)
    117     {
    118         if (dcmp(C1.r - C2.r) == 0)    return -1;
    119         return 0;
    120     }
    121     if (dcmp(C1.r + C2.r - d) < 0)    return 0;
    122     if (dcmp(fabs(C1.r - C2.r) - d) > 0)    return 0;
    123 
    124     double a = angle(C2.c - C1.c);
    125     double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (2*C1.r*d));
    126     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
    127 
    128     v.push_back(p1);
    129     if (p1 == p2)    return 1;
    130     v.push_back(p2);
    131     return 2;
    132 }
    133 
    134 void CircumscribedCircle()
    135 {
    136     Point P[3];
    137     for (int i = 0; i < 3; i++)    scanf("%lf%lf", &P[i].x, &P[i].y);
    138 
    139     Point c = Get_Line_Intersect((P[0] + P[1])/2, Rotate(P[1] - P[0], PI/2), (P[2] + P[0])/2, Rotate(P[2] - P[0], -PI/2));
    140 
    141     printf("(%.6lf,%.6lf,%.6lf)
    ", c.x, c.y, Length(c - P[0]));
    142 }
    143 
    144 void InscribedCircle()
    145 {
    146     Point P[3];
    147     for (int i = 0; i < 3; i++)    scanf("%lf%lf", &P[i].x, &P[i].y);
    148 
    149     Vector v1 = Rotate(P[1] - P[0], (Cross(P[2] - P[0], P[1] - P[0]) > 0 ? -1 : 1) * Angle(P[1]-P[0], P[2]-P[0]) / 2);
    150     Vector v2 = Rotate(P[0] - P[1], (Cross(P[2] - P[1], P[0] - P[1]) > 0 ? -1 : 1) * Angle(P[0]-P[1], P[2]-P[1]) / 2);
    151     Point c = Get_Line_Intersect(P[0], v1, P[1], v2);
    152 
    153     printf("(%.6lf,%.6lf,%.6lf)
    ", c.x, c.y, Distance_to_Line(c, P[0], P[1]));    
    154 }
    155 
    156 void TangentLineThroughPoint()
    157 {
    158     Circle C;
    159     Point P;
    160     vector<double> v;
    161     scanf("%lf%lf%lf", &C.c.x, &C.c.y, &C.r);
    162     scanf("%lf%lf", &P.x, &P.y);
    163 
    164     printf("[");
    165     if (getTangents(P, C, v))    sort(v.begin(), v.end()), printf("%.6lf", v[0]);
    166     if (v.size() == 2)    printf(",%.6lf", v[1]);
    167     printf("]
    ");
    168 }
    169 
    170 void CircleThroughAPointAndTangentToALineWithRadius()
    171 {
    172     Circle P;
    173     Point A, B;
    174     scanf("%lf%lf%lf%lf%lf%lf%lf", &P.c.x, &P.c.y, &A.x, &A.y, &B.x, &B.y, &P.r);
    175 
    176     Line original(A, B - A);
    177     vector<Point> v;
    178     get_Line_Circle_Intersection(original.move(P.r), P, v);
    179     get_Line_Circle_Intersection(original.move(-P.r), P, v);
    180     sort(v.begin(), v.end());
    181 
    182     printf("[");
    183     if (v.size())    printf("(%.6lf,%.6lf)", v[0].x, v[0].y);
    184     for (int i = 1; i < v.size(); i++)    printf(",(%.6lf,%.6lf)", v[i].x, v[i].y);
    185     printf("]
    ");
    186 }
    187 
    188 inline Point e_to_go(Vector A, double len) { return A / Length(A) * len; }
    189 
    190 void CircleTangentToTwoLinesWithRadius()
    191 {
    192     Point A, B, C ,D;
    193     double r;
    194     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);
    195 
    196     vector<Point> v;
    197     int control = Cross(B - A, D - C) < 0 ? -1 : 1;
    198 
    199     Point P = Get_Line_Intersect(A, B-A, C, D-C);
    200     double seta = Angle(B - A, D - C)/2;
    201     Vector v1 = Rotate(B - A, control*seta);
    202     Vector v2 = Rotate(B - A, -control*(PI/2 - seta));
    203 
    204     v.push_back(P + e_to_go(v1, r/sin(seta)));
    205     v.push_back(P - e_to_go(v1, r/sin(seta)));
    206     v.push_back(P + e_to_go(v2, r/cos(seta)));
    207     v.push_back(P - e_to_go(v2, r/cos(seta)));
    208     sort(v.begin(), v.end());
    209 
    210     for (int i = 0; i < v.size(); i++)
    211         printf("%c(%.6lf,%.6lf)", ",["[i == 0], v[i].x, v[i].y);
    212     printf("]
    ");
    213 }
    214 
    215 void CircleTangentToTwoDisjointCirclesWithRadius()
    216 {
    217     Circle C1, C2;
    218     double r;
    219     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);
    220     C1.r += r, C2.r += r;
    221     vector<Point> v;
    222     get_Circle_Circle_Intersection(C1, C2, v);
    223     sort(v.begin(), v.end());
    224 
    225     if (!v.size())    printf("[");
    226     for (int i = 0; i < v.size(); i++)
    227         printf("%c(%.6lf,%.6lf)", ",["[i == 0], v[i].x, v[i].y);
    228     printf("]
    ");
    229 }
    230 
    231 int main()
    232 {
    233     string s;
    234     while (cin >> s)
    235     {
    236         if (s.length() < 19)    InscribedCircle();
    237         else
    238         {
    239             switch(s[18])
    240             {
    241                 case 'e':
    242                     CircumscribedCircle(); break;
    243                 case 'P':
    244                     TangentLineThroughPoint(); break;
    245                 case 't':
    246                     CircleThroughAPointAndTangentToALineWithRadius(); break;
    247                 case 'L':
    248                     CircleTangentToTwoLinesWithRadius(); break;
    249                 case 'D':
    250                     CircleTangentToTwoDisjointCirclesWithRadius(); break;
    251                 default : break;
    252             }
    253         }
    254     }
    255     return 0;
    256 }
    View Code
  • 相关阅读:
    power designer 水电费缴纳系统的设计
    水电费管理系统需求分析----表格的建立
    GUID
    Java对象的序列化
    模拟银行自动终端系统
    随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。
    Cookie的简易用法
    工作任务:题目一:网页输出九九乘法表;题目二:网页输出三角形和菱形
    简单的sql注入
    10-18 Oracle 基础练习
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10200931.html
Copyright © 2020-2023  润新知