首页 > 其他 > 详细

ZOJ3238 Water Ring(计算几何)

时间:2014-04-04 12:40:56      阅读:398      评论:0      收藏:0      [点我收藏+]

题意:给你一个圆形和很多个矩形,然后要你求圆形的圆周有多少被矩形覆盖。

思路:比赛的时候是有思路的了,不过一直在调别的题,最后剩下30分钟肯定来不及敲。想法是这样的,要是我们可以求出每个矩形覆盖了圆周的哪些区间,我们最后就对这些区间排序然后求区间和就好了,但是问题是怎么知道哪些区间是要的,哪些区间是不要的呢? 首先我们对矩形的四条线段和矩形求交,把所有的交点求出来,然后将交点用atan2转化成极角(我用的区间是[0,2pi]),实际上直接用极角肯定也没问题吧),然后排序,排序之后我们会发现我们要的区间一定是相邻的两个角度的点对应的区间,但是有可能这些区间是不是我们要的,判断的条件就是两个角度的对应的弧段的中点如果在矩形里面的话我们就将这个区间保留。

如此一来就将所有的区间弄了出来,接下来就是求线段的并的总长度了,for一下就好。

但是后来WA了一发,原因是如果圆完全被矩形包含的话,我们解不出交点,会被默认答案是0,所以上面的方法只有在有交点的时候成立,所以判的时候加多一个判是否被完全包含,被完全包含最后直接输出2*pi*r就好,代码写的略长= =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<string>
#define maxn 150
#define eps 1e-7
using namespace std;
 
const double pi = acos(-1.0);
 
struct Point
{
    double x, y;
    Point(double xi, double yi) :x(xi), y(yi){}
    Point(){}
    Point operator + (const Point &b){
        return Point(x + b.x, y + b.y);
    }
    Point operator - (const Point &b){
        return Point(x - b.x, y - b.y);
    }
    double ang(){
        double res=atan2(y,x);
        if (res < 0) return res + 2*pi;
        else return res;
    }
    Point rot(double ag){
        return Point(x*cos(ag) - y*sin(ag), x*sin(ag) + y*cos(ag));
    }
};
 
struct Seg
{
    Point st, ed;
    Seg(Point sti, Point edi) :st(sti), ed(edi){}
    Seg(){}
};
 
struct Inter
{
    double l, r;
    Inter(double li, double ri) :l(li), r(ri){}
    Inter(){}
    bool operator < (const Inter &b) const{
        if (l == b.l) return r < b.r;
        else return l < b.l;
    }
};
 
int dcmp(double x){
    return (x>eps) - (x < -eps);
}
 
double ctr;
int n;
 
vector<double> getInterSection(Seg seg){
    vector<double> res;
    if (seg.st.x == seg.ed.x){
        double xx = seg.st.x;
        double y1 = seg.st.y, y2 = seg.ed.y;
        if (dcmp(abs(xx) - ctr) > 0) return res;
        else if (dcmp(abs(xx) - ctr) == 0){
            if (0 >= y1 && 0 <= y2){
                res.push_back(Point(xx, 0).ang());
            }
        }
        else{
            double dy = sqrt(ctr*ctr - xx*xx);
            if (dy >= y1&&dy <= y2){
                res.push_back(Point(xx, dy).ang());
            }
            dy = -dy;
            if (dy >= y1&&dy <= y2){
                res.push_back(Point(xx, dy).ang());
            }
        }
    }
    else{
        double yy = seg.st.y;
        double x1 = seg.st.x, x2 = seg.ed.x;
        if (dcmp(abs(yy) - ctr) > 0) return res;
        else if (dcmp(abs(yy) - ctr) == 0){
            if (0 >= x1 && 0 <= x2){
                res.push_back(Point(0, yy).ang());
            }
        }
        else{
            double dx = sqrt(ctr*ctr - yy*yy);
            if (dx >= x1&&dx <= x2){
                res.push_back(Point(dx, yy).ang());
            }
            dx = -dx;
            if (dx >= x1&&dx <= x2){
                res.push_back(Point(dx, yy).ang());
            }
        }
    }
    return res;
}
 
bool withinRect(double xx,double yy, double li, double lj, double ri, double rj){
    return xx >= li&&xx <= ri&&yy >= lj&&yy <= rj;
}
 
int main()
{
    while (cin >> ctr >> n){
        double li, lj, ri, rj;
        Seg seg;
        vector<double> tot;
        vector<double> tmp;
        vector<Inter> inter; bool flag = false;
        for (int i = 0; i < n; i++){
            scanf("%lf%lf%lf%lf", &li, &lj, &ri, &rj);
            if (flag) continue;
            if (li <= -ctr && ctr <= ri && lj <= -ctr&&ctr <= rj){
                flag = true; continue;
            }
            tot.clear();
            seg.st = Point(li, lj); seg.ed = Point(li, rj);
            tmp = getInterSection(seg);
            tot.insert(tot.end(), tmp.begin(), tmp.end());
 
            seg.st = Point(ri, lj); seg.ed = Point(ri, rj);
            tmp = getInterSection(seg);
            tot.insert(tot.end(), tmp.begin(), tmp.end());
 
            seg.st = Point(li, lj); seg.ed = Point(ri, lj);
            tmp = getInterSection(seg);
            tot.insert(tot.end(), tmp.begin(), tmp.end());
 
            seg.st = Point(li, rj); seg.ed = Point(ri, rj);
            tmp = getInterSection(seg);
            tot.insert(tot.end(), tmp.begin(), tmp.end());
 
            sort(tot.begin(), tot.end());
            int siz = tot.size();
            for (int k = 0; k < siz; k++){
                if (dcmp(tot[k] - tot[(k + 1) % siz]) == 0) continue;
                Point mid;
                if (dcmp(tot[(k + 1) % siz] - tot[k])>0) mid = Point(ctr, 0).rot((tot[k] + tot[(k + 1) % siz]) / 2);
                else mid = Point(ctr, 0).rot((tot[k] + tot[(k + 1) % siz]-2*pi) / 2);
                if (withinRect(mid.x, mid.y, li, lj, ri, rj)){
                    if (dcmp(tot[(k + 1) % siz] - tot[k]) >= 0){
                        inter.push_back(Inter(tot[k], tot[(k + 1) % siz]));
                    }
                    else{
                        inter.push_back(Inter(0, tot[(k+1)%siz]));
                        inter.push_back(Inter(tot[k % siz], 2 * pi));
                    }
                }
            }
        }
        sort(inter.begin(), inter.end());
        double ans = 0;
        if (flag) {
            printf("%.3lf\n", 2 * pi*ctr); continue;
        }
        if (inter.size() == 0) {
            printf("%.3lf\n", ans); continue;
        }
        double lt = inter[0].l, rt = inter[0].r;
        for (int i = 1; i < inter.size(); i++){
            if (inter[i].l <= rt){
                rt = max(rt, inter[i].r);
            }
            else{
                ans += rt - lt;
                lt = inter[i].l, rt = inter[i].r;
            }
        }
        ans += rt - lt;
        printf("%.3lf\n", ans*ctr);
    }
    return 0;
}

 

ZOJ3238 Water Ring(计算几何),布布扣,bubuko.com

ZOJ3238 Water Ring(计算几何)

原文:http://www.cnblogs.com/chanme/p/3643782.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!