2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】
CSGO
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 127 Accepted Submission(s): 20
Problem Description
Senior Pan is crazy about CSGO and she is so skilled. She can kill every enemy she spots at the same time, even if they are in different positions. There are some walls in a map. The locations of enemies are represented by some points and walls are represented by some line segments in the XY plane. The position of senior Pan is also described as a point. Senior Pan can spot an enemy if and only if the segment between them doesn’t intersect with any wall segment. But if there are other enemies on this segment, she can kill all of them. For some given positions, senior Pan wants to know how many enemies she can kill in these positions. Your Task is to write a program to figure it out.
Input
∙ The input contains multiple test cases, each of them are described below. ∙ The first line contains three integers N, M, Q representing respectively the number of enemies, the number of walls and the number of positions senior Pan chooses. For the next N lines, each line contain two integers X and Y, indicating the location of enemies is (X, Y). The next M lines, each line contain four integers X1, Y1, X2, Y2, indicating two endpoints of the wall are (X1, Y1) and (X2, Y2). The last Q lines, each line contain two integers X and Y, indicating the location of senior Pan chooses is (X, Y). ∙ You can assume that walls don’t intersect even if in their endpoints, no enemies have the same location and no enemies are in walls. ∙ N, M <= 10 ^ 4. ∙ Q <= 12. ∙ -10 ^ 6 <= X, Y, X1, Y1, X2, Y2 <= 10 ^ 6
Output
For each test case, output "Case #x: " in the first line (without quotes). For next Q lines, each line output a number which represents the number of enemies senior Pan can kill in her i-th chosen location.
Sample Input
3 2 1
1 1
2 2
-1 1
0 1 -1 0
2 -2 2 0
0 0
5 4 2
29 -8
19 33
-46 -44
-38 19
9 -20
40 45 38 18
9 -32 -8 46
33 20 35 -19
22 17 -5 40
19 -38
-17 -21
Sample Output
Case #1:
2
Case #2:
3
2
Source
2017 Multi-University Training Contest - Team 9
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6163
分析: 平面上有一些点和一些线段,保证这些线段互不相交,点不在线段上。 每次问从一个点能看到多少个点。一个点能看到另一点当且仅当这两点连线的线段不和任何一个已知的线段相交。(这里的相交均指非规范相交) 每次以询问点为极点极角排序。线段两端点拆成两个事件,一次出现,一次消失。对于枚举的某一个角度,能否看见当前角度的点仅取决于当前角度上离极点最近的线段,由于保证线段不相交,一条线段在插入时和还存在线段的相对位置是不会改变的,所以可以用set维护,每次先处理当前角度上所有的点是否被线段遮挡就可以了。
复杂度是O(Q(N + M)log(N + M))。
下面给出AC代码:
1 #include<bits/stdc++.h>
2
3 using namespace std;
4 const int N = 11000;
5 const double eps = 1e-10;
6 const double pi = acos(-1.0);
7 typedef complex<double> Point;
8
9 double Det(const Point & a, const Point & b) {return (conj(a) * b).imag();}
10 double Dot(const Point & a, const Point & b) {return (conj(a) * b).real();}
11 int sgn(double x) {if(fabs(x) < eps) return 0; if(x > eps) return 1; return -1;}
12
13 double _ang;
14 Point ori = (Point) {0, 0};
15 struct Line :public vector<Point>{
16 double k;
17 Line(){}
18 Line(Point a, Point b){
19 push_back(a), push_back(b);
20 k = atan2((b - a).imag(), (b - a).real());
21 }
22 };
23 Point Vec(Line a) {return a[1] - a[0];}
24 Point LineIntersection(const Line & a, const Line & b){
25 double k1 = Det(Vec(a), Vec(b));
26 double k2 = Det(Vec(b), a[0] - b[0]);
27 if(!sgn(k1)){
28 if(sgn(abs(a[1] - b[0]) - abs(a[0] - b[0])) > 0) return a[0];
29 else return a[1];
30 }
31 return a[0] + Vec(a) * k2 / k1;
32 }
33
34 bool operator < (const Line & a, const Line & b){
35 Line cur = (Line) {ori, (Point) {cos(_ang), sin(_ang)}};
36 if(sgn(abs(LineIntersection(a, cur)) - abs(LineIntersection(b, cur))) < 0) return 1;
37 return 0;
38 }
39
40 struct Event{
41 double k;
42 int id, typ;
43 bool operator < (const Event & a) const{
44 if(sgn(k - a.k)) return k < a.k;
45 return typ < a.typ;
46 }
47 };
48
49 double CalcAng(const Point & a) {return atan2(a.imag(), a.real());}
50 Point p[N];
51 Line w[N], seg[N];
52 Event e[N << 3];
53
54 int q, n, m, tot;
55 set<Line> s;
56 int rec[N];
57
58 int Calc(int x){
59 tot = 0;
60 s.clear();
61 for(int i = 1; i <= n; i ++)
62 e[++ tot] = (Event){CalcAng(p[i] - p[x]), i, 1};
63
64 bool flag = 0;
65 for(int i = 1; i <= m; i++){
66 seg[i] = (Line) {w[i][0] - p[x], w[i][1] - p[x]};
67 if(sgn(CalcAng(seg[i][0]) - CalcAng(seg[i][1])) > 0) swap(seg[i][0], seg[i][1]);
68 flag = 1;
69 if(sgn(Det(Vec(seg[i]), Point(-1, 0))) != 0 && sgn(abs(CalcAng(seg[i][0]) - CalcAng(seg[i][1])) - pi) > 0) flag = 0;
70 if(flag) e[++ tot] = (Event) {CalcAng(seg[i][0]), i, 0}, e[++tot] = (Event) {CalcAng(seg[i][1]), i, 2};
71 else{
72 e[++ tot] = (Event) {-pi, i, 0};
73 e[++ tot] = (Event) {CalcAng(seg[i][0]), i, 2};
74 e[++ tot] = (Event) {CalcAng(seg[i][1]), i, 0};
75 e[++ tot] = (Event) {pi, i, 2};
76 }
77 }
78
79 sort(e + 1, e + tot + 1);
80 int cnt = 0;
81 Point dir, dd;
82 Line t;
83 for(int i = 1; i <= tot; i ++){
84 _ang = e[i].k;
85 if(e[i].typ & 1){
86 dir = (Point) {cos(_ang), sin(_ang)};
87 if(s.empty() || sgn(abs(LineIntersection(*s.begin(), (Line) {ori, dir})) - abs(p[e[i].id] - p[x])) > 0){
88 cnt ++, rec[cnt] = e[i].id;
89 }
90 }
91 else if(!e[i].typ) s.insert(seg[e[i].id]);
92 else s.erase(seg[e[i].id]);
93 }
94
95 return cnt;
96 }
97
98 int Tcase;
99
100 char fi[100] = "pcx.in", fo[100] = "pcx.ans";
101 void Solve(){
102 printf("Case #%d:n", ++ Tcase);
103 double x, y;
104 Point a, b;
105 for(int i = 1; i <= n; i ++){
106 scanf("%lf%lf", &x, &y);
107 p[i] = (Point) {x, y};
108 }
109 for(int i = 1; i <= m; i ++){
110 scanf("%lf%lf", &x, &y);
111 a = (Point) {x, y};
112 scanf("%lf%lf", &x, &y);
113 b = (Point) {x, y};
114 w[i] = (Line) {a, b};
115 }
116
117 int ans;
118 for(int i = 1; i <= q; i ++){
119 scanf("%lf%lf", &x, &y);
120 p[n + 1] = (Point) {x, y};
121 ans = Calc(n + 1);
122 printf("%dn", ans);
123 }
124
125 return;
126 }
127
128 int main(){
129 // freopen("_pc.in", "r", stdin);
130 // freopen("_pc.ans", "w", stdout);
131 while(~scanf("%d%d%d", &n, &m, &q))
132 Solve();
133 //printf("--->%lfn", (double) clock() / CLOCKS_PER_SEC);
134 return 0;
135 }
- iOS多线程——你要知道的NSThread都在这里你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里
- KVO、Delegate、Notification 区别及相关使用场景你要知道的KVC、KVO、Delegate、Notification都在这里
- Core ML简介及实时目标检测及Caffe TensorFlow coremltools模型转换
- iOS网络——NSURLSession详解及SDWebImage源码解析你要知道的NSURLSession都在这里
- BZOJ3585: mex(主席树)
- 01.LoT.UI 前后台通用框架分解系列之——小图片背景全屏显示(可自动切换背景)
- 02.LoT.UI 前后台通用框架分解系列之——灵活的菜单栏
- 05.LoT.UI 前后台通用框架分解系列之——漂亮的时间选择器
- 06.LoT.UI 前后台通用框架分解系列之——浮夸的图片上传
- 07.LoT.UI 前后台通用框架分解系列之——轻巧的文本编辑器
- 07.LoT.UI 前后台通用框架分解系列之——强大的文本编辑器
- 洛谷P3358 最长k可重区间集问题(费用流)
- 08.LoT.UI 前后台通用框架分解系列之——多样的Tag选择器
- iOS多线程——RunLoop与GCD、AutoreleasePool你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用 Jenkins 和 Ansible 实现 CI/CD
- 太刺激了,面试官让我手写跳表,而我用两种实现方式吊打了TA!
- 被 Google 选择的下一代数据面 Cilium 是什么 - 上手实践
- K8S 生态周报| 是时候从 k8s v1.16 升级了
- ESP8266(一)| 基于OneNet的温度采集显示系统
- 隐秘的 MySQL 类型转换
- 对Jenkinsfile语法说不,开源项目Jenkins Json Build挺你
- Volatile概述
- SparkStreaming和Kafka基于Direct Approach如何管理offset
- Spark在处理数据的时候,会将数据都加载到内存再做处理吗?
- 美团点评2020年测试工程师笔试题
- Pytest之重运行及生成测试报告
- 一条SQL的奇妙旅行
- 表格的融合
- 解放双手,使用批处理达到账号密码之类再也用不着手动输入!