zoukankan      html  css  js  c++  java
  • uva 12296 Pieces and Discs

    题意:

    有个矩形,左下角(0,0),左上角(L,W).

    思路:

    除了圆盘之外,本题的输入也是个PSLG,因此可以按照前面叙述的算法求出各个区域:只需把线段视为直线,用切割凸多边形的方法 :每次读入线段,切割所有块,最终得到若干凸多边形

    如何判断多边形是否与圆盘相交:如果多边形的边和圆周规范相交,圆盘和多边形一定相交,

     1:即使完全没有公共点,也可以相交,互相内含 需要判断多边形是否有顶点在园内,还需要判断圆心是否在多边形内;

    2.如果不规范:  a:带判断的线段在园外;

    b:带判断的线段在园内即两个端点在圆上,只需要判断中点是否在园内;

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<iostream>
      6 #include<memory.h>
      7 #include<cstdlib>
      8 #include<vector>
      9 #define clc(a,b) memset(a,b,sizeof(a))
     10 #define LL long long int
     11 #define up(i,x,y) for(i=x;i<=y;i++)
     12 #define w(a) while(a)
     13 const double inf=0x3f3f3f3f;
     14 const double eps = 1e-8;
     15 const double PI = acos(-1.0);
     16 using namespace std;
     17 
     18 double dcmp(double x)
     19 {
     20     if(fabs(x) < eps) return 0;
     21     else return x < 0 ? -1 : 1;
     22 }
     23 
     24 struct Point
     25 {
     26     double x, y;
     27     Point(double x=0, double y=0):x(x),y(y) { }
     28 };
     29 
     30 typedef Point Vector;
     31 
     32 typedef vector<Point> Polygon;
     33 
     34 Vector operator + (Vector A, Vector B)
     35 {
     36     return Vector(A.x+B.x, A.y+B.y);
     37 }
     38 
     39 Vector operator - (Point A, Point B)
     40 {
     41     return Vector(A.x-B.x, A.y-B.y);
     42 }
     43 
     44 Vector operator * (Vector A, double p)
     45 {
     46     return Vector(A.x*p, A.y*p);
     47 }
     48 
     49 double Dot(Vector A, Vector B)
     50 {
     51     return A.x*B.x + A.y*B.y;
     52 }
     53 double Cross(Vector A, Vector B)
     54 {
     55     return A.x*B.y - A.y*B.x;
     56 }
     57 double Length2(Vector A)
     58 {
     59     return Dot(A, A);
     60 }
     61 
     62 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
     63 {
     64     Vector u = P-Q;
     65     double t = Cross(w, u) / Cross(v, w);
     66     return P+v*t;
     67 }
     68 
     69 bool OnSegment(Point p, Point a1, Point a2)
     70 {
     71     return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
     72 }
     73 
     74 // 多边形的有向面积
     75 double PolygonArea(Polygon poly)
     76 {
     77     double area = 0;
     78     int n = poly.size();
     79     for(int i = 1; i < n-1; i++)
     80         area += Cross(poly[i]-poly[0], poly[(i+1)%n]-poly[0]);
     81     return area/2;
     82 }
     83 
     84 // cut with directed line A->B, return the left part
     85 // may return a single point or a line segment
     86 Polygon CutPolygon(Polygon poly, Point A, Point B)
     87 {
     88     Polygon newpoly;
     89     int n = poly.size();
     90     for(int i = 0; i < n; i++)
     91     {
     92         Point C = poly[i];
     93         Point D = poly[(i+1)%n];
     94         if(dcmp(Cross(B-A, C-A)) >= 0) newpoly.push_back(C);
     95         if(dcmp(Cross(B-A, C-D)) != 0)
     96         {
     97             Point ip = GetLineIntersection(A, B-A, C, D-C);
     98             if(OnSegment(ip, C, D)) newpoly.push_back(ip);
     99         }
    100     }
    101     return newpoly;
    102 }
    103 
    104 int isPointInPolygon(Point p, Polygon v)
    105 {
    106     int wn = 0;
    107     int n = v.size();
    108     for(int i = 0; i < n; i++)
    109     {
    110         if(OnSegment(p, v[i], v[(i+1)%n])) return -1; // 在边界上
    111         int k = dcmp(Cross(v[(i+1)%n]-v[i], p-v[i]));
    112         int d1 = dcmp(v[i].y - p.y);
    113         int d2 = dcmp(v[(i+1)%n].y - p.y);
    114         if(k > 0 && d1 <= 0 && d2 > 0) wn++;
    115         if(k < 0 && d2 <= 0 && d1 > 0) wn--;
    116     }
    117     if (wn != 0) return 1; // 内部
    118     return 0; // 外部
    119 }
    120 
    121 // 点在圆心内。圆周上不算
    122 bool isInCircle(Point p, Point center, double R)
    123 {
    124     return dcmp(Length2(p-center) - R*R) < 0;
    125 }
    126 
    127 // 直线AB和圆心为C,半径为r的圆的交点
    128 // 返回交点个数,t1, t2分别为两个交点在直线方程中的参数,p1和p2为交点本身
    129 int getLineCircleIntersection(Point A, Point B, Point C, double r, double& t1, double& t2)
    130 {
    131     // 初始方程:(A.x + t(B.x - A.x) - C.x)^2 + (A.y + t(B.y - A.y) - C.y)^2 = r^2
    132     // 整理得:(at + b)^2 + (ct + d)^2 = r^2
    133     double a = B.x - A.x;
    134     double b = A.x - C.x;
    135     double c = B.y - A.y;
    136     double d = A.y - C.y;
    137     // 展开得:(a^2 + c^2)t^2 + 2(ab + cd)t + b^2 + d^2 - r^2 = 0,即et^2 + ft + g = 0
    138     double e = a * a + c * c;
    139     double f = 2 * (a * b + c * d);
    140     double g = b * b + d * d - r * r;
    141     double delta = f * f - 4 * e * g; // 判别式
    142     if(dcmp(delta) < 0) return 0; // 相离
    143     if(dcmp(delta) == 0)  // 相切
    144     {
    145         t1 = t2 = -f / (2 * e);
    146         return 1;
    147     }
    148     t1 = (-f - sqrt(delta)) / (2 * e);
    149     t2 = (-f + sqrt(delta)) / (2 * e);
    150     return 2;
    151 }
    152 
    153 // 圆和线段是否相交(相切不算)。线段不考虑端点
    154 bool CircleIntersectSegment(Point A, Point B, Point p, double R)
    155 {
    156     double t1, t2;
    157     int c = getLineCircleIntersection(A, B, p, R, t1, t2);
    158     if(c <= 1) return false;
    159     if(dcmp(t1) > 0 && dcmp(t1-1) < 0) return true; // 端点在圆上
    160     if(dcmp(t2) > 0 && dcmp(t2-1) < 0) return true;
    161     return false;
    162 }
    163 
    164 /////////// 题目相关
    165 vector<Polygon> pieces, new_pieces;
    166 
    167 void cut(int x1, int y1, int x2, int y2)
    168 {
    169     new_pieces.clear();
    170     for(int i = 0; i < pieces.size(); i++)
    171     {
    172         Polygon left = CutPolygon(pieces[i], Point(x1, y1), Point(x2, y2));
    173         Polygon right = CutPolygon(pieces[i], Point(x2, y2), Point(x1, y1));
    174         if(left.size() >= 3) new_pieces.push_back(left);
    175         if(right.size() >= 3) new_pieces.push_back(right);
    176     }
    177     pieces = new_pieces;
    178 }
    179 
    180 bool DiscIntersectPolygon(Polygon poly, Point p, double R)
    181 {
    182     if(isPointInPolygon(p, poly) != 0) return true;
    183     if(isInCircle(poly[0], p, R)) return true;
    184     int n = poly.size();
    185     for(int i = 0; i < n; i++)
    186     {
    187         if(CircleIntersectSegment(poly[i], poly[(i+1)%n], p, R))
    188         {
    189             return true; // 不考虑线段端点
    190         }
    191         if(isInCircle((poly[i]+poly[(i+1)%n])*0.5, p, R))
    192         {
    193             return true; // 两个端点都在圆上
    194         }
    195     }
    196     return false;
    197 }
    198 
    199 void query(Point p, int R)
    200 {
    201     vector<double> ans;
    202     for(int i = 0; i < pieces.size(); i++)
    203     {
    204         if(DiscIntersectPolygon(pieces[i], p, R))
    205         {
    206             ans.push_back(fabs(PolygonArea(pieces[i])));
    207         }
    208     }
    209     printf("%d", ans.size());
    210     sort(ans.begin(), ans.end());
    211     for(int i = 0; i < ans.size(); i++)
    212         printf(" %.2lf", ans[i]);
    213     printf("
    ");
    214 }
    215 
    216 int main()
    217 {
    218     int n, m, L, W;
    219     while(scanf("%d%d%d%d", &n, &m, &L, &W) == 4 && n)
    220     {
    221         pieces.clear();
    222 
    223         Polygon bbox;
    224         bbox.push_back(Point(0, 0));
    225         bbox.push_back(Point(L, 0));
    226         bbox.push_back(Point(L, W));
    227         bbox.push_back(Point(0, W));
    228         pieces.push_back(bbox);
    229 
    230         for(int i = 0; i < n; i++)
    231         {
    232             int x1, y1, x2, y2;
    233             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    234             cut(x1, y1, x2, y2);
    235         }
    236 
    237         for(int i = 0; i < m; i++)
    238         {
    239             int x, y, R;
    240             scanf("%d%d%d", &x, &y, &R);
    241             query(Point(x, y), R);
    242         }
    243         printf("
    ");
    244     }
    245     return 0;
    246 }
    View Code
  • 相关阅读:
    oo第二阶段总结
    oo第一阶段总结
    散列函数的应用及其安全性
    【记下来,以后教给孩子玩】汉诺塔移动小窍门
    结对项目-四则运算出题程序(GUI版)
    读《构建之法》第四章、第十七章有感
    2016012002+小学四则运算练习软件项目报告
    Week2-作业1:阅读与博客
    阴差阳错是最好的安排
    2016011986卢琪信息安全作业5
  • 原文地址:https://www.cnblogs.com/ITUPC/p/4896380.html
Copyright © 2011-2022 走看看