POJ 3335 Rotating Scoreboard

Description:

This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spectators are seated along the edges of the polygon. We want to place a rotating scoreboard somewhere in the hall such that a spectator sitting anywhere on the boundary of the hall can view the scoreboard (i.e., his line of sight is not blocked by a wall). Note that if the line of sight of a spectator is tangent to the polygon boundary (either in a vertex or in an edge), he can still view the scoreboard. You may view spectator’s seats as points along the boundary of the simple polygon, and consider the scoreboard as a point as well. Your program is given the corners of the hall (the vertices of the polygon), and must check if there is a location for the scoreboard (a point inside the polygon) such that the scoreboard can be viewed from any point on the edges of the polygon.

Input:

The first number in the input line, T is the number of test cases. Each test case is specified on a single line of input in the form n x1 y1 x2 y2 … xn yn where n (3 ≤ n ≤ 100) is the number of vertices in the polygon, and the pair of integers xi yi sequence specify the vertices of the polygon sorted in order.

Output:

The output contains T lines, each corresponding to an input test case in that order. The output line contains either YES or NO depending on whether the scoreboard can be placed inside the hall conforming to the problem conditions.

Sample Input:

2
4 0 0 0 1 1 1 1 0
8 0 0 0 2 1 2 1 1 2 1 2 2 3 2 3 0

Sample Output:

YES
NO

题目链接

判断多边形是否有内核。

半平面交直接用模板即可。

AC代码:

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
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 1e2 + 5;
const double eps = 1e-8;

int Sgn(double X) {
if (fabs(X) < eps) {
return 0;
}
return X < 0 ? -1 : 1;
}

struct Point {
double X, Y;

Point() {}
Point(double _X, double _Y) {
X = _X;
Y = _Y;
}

void Input() {
scanf("%lf%lf", &X, &Y);
}

Point operator - (const Point &B) const {
return Point(X - B.X, Y - B.Y);
}

double operator * (const Point &B) const {
return X * B.X + Y * B.Y;
}

double operator ^ (const Point &B) const {
return X * B.Y - Y * B.X;
}
};

struct Segment {
Point S, T;

Segment() {}
Segment(Point _S, Point _T) {
S = _S;
T = _T;
}

double operator ^ (const Segment &B) const {
return (T - S) ^ (B.T - B.S);
}
};

bool IsParallel(Segment A, Segment B) {
return Sgn((A.T - A.S) ^ (B.T - B.S)) == 0;
}

Point IntersectionPoint(Segment A, Segment B) {
double X = (B.T - B.S) ^ (A.S - B.S), Y = (B.T - B.S) ^ (A.T - B.S);
return Point((A.S.X * Y - A.T.X * X) / (Y - X), (A.S.Y * Y - A.T.Y * X) / (Y - X));
}

// 半平面,表示S->T逆时针(左侧)的半平面
struct HalfPlane:public Segment {
double Angle;

HalfPlane() {}
HalfPlane(Point _S, Point _T) {
S = _S;
T = _T;
}
HalfPlane(Segment _ST) {
S = _ST.S;
T = _ST.T;
}

// 计算极角
void CalAngle() {
Angle = atan2(T.Y - S.Y, T.X - S.X);
}

// 极角排序
bool operator < (const HalfPlane &B) const {
return Angle < B.Angle;
}
};

int T;
int N;
int Tot;
HalfPlane halfplanes[maxn];
Point points[maxn];
int Front, Tail;
int Que[maxn];

void Push(HalfPlane X) {
halfplanes[Tot++] = X;
}

void Unique() {
int Cnt = 1;
for (int i = 1; i < Tot; ++i) {
if (Sgn(halfplanes[i].Angle - halfplanes[i - 1].Angle) != 0) {
halfplanes[Cnt++] = halfplanes[i];
}
else if (Sgn((halfplanes[Cnt - 1].T - halfplanes[Cnt - 1].S) ^ (halfplanes[i].S - halfplanes[Cnt - 1].S)) > 0) {
halfplanes[Cnt - 1] = halfplanes[i];
}
}
Tot = Cnt;
}

bool HalfPlaneInsert() {
for (int i = 0; i < Tot; ++i) {
halfplanes[i].CalAngle();
}
sort(halfplanes, halfplanes + Tot);
Unique();
Que[Front = 0] = 0;
Que[Tail = 1] = 1;
points[1] = IntersectionPoint(halfplanes[0], halfplanes[1]);
for (int i = 2; i < Tot; ++i) {
while (Front < Tail && Sgn((halfplanes[i].T - halfplanes[i].S) ^ (points[Tail] - halfplanes[i].S)) < 0) {
Tail--;
}
while (Front < Tail && Sgn((halfplanes[i].T - halfplanes[i].S) ^ (points[Front + 1] - halfplanes[i].S)) < 0) {
Front++;
}
Que[++Tail] = i;
if (IsParallel(halfplanes[i], halfplanes[Que[Tail - 1]])) {
return false;
}
points[Tail] = IntersectionPoint(halfplanes[i], halfplanes[Que[Tail - 1]]);
}
while (Front < Tail && Sgn((halfplanes[Que[Front]].T - halfplanes[Que[Front]].S) ^ (points[Tail] - halfplanes[Que[Front]].S)) < 0) {
Tail--;
}
while (Front < Tail && Sgn((halfplanes[Que[Tail]].T - halfplanes[Que[Tail]].S) ^ (points[Front + 1] - halfplanes[Que[Tail]].S)) < 0) {
Front++;
}
if (Front + 1 >= Tail) {
return false;
}
return true;
}

int main(int argc, char *argv[]) {
scanf("%d", &T);
for (int Case = 1; Case <= T; ++Case) {
Tot = 0;
scanf("%d", &N);
for (int i = 0; i < N; ++i) {
points[i].Input();
}
reverse(points, points + N);
for (int i = 0; i < N; ++i) {
Push(HalfPlane(points[i], points[(i + 1) % N]));
}
if (HalfPlaneInsert()) {
printf("YES\n");
}
else {
printf("NO\n");
}
}
return 0;
}
文章目录
  1. 1. Description:
  2. 2. Input:
  3. 3. Output:
  4. 4. Sample Input:
  5. 5. Sample Output:
    1. 5.1. 题目链接
  6. 6. AC代码:
|