HDU_6590 Code 【凸包】
一、题目
二、分析
题目描述了一大堆东西,就是想问二维空间里,能不能确定$d w_1 w_2$使得函数满足$f(x_1,x_2) = y$,并且$sign(x)$函数是一个信号函数,只取3种值。
那么将函数拆开其实就是$d + w_{1}x_{i_1} + w_{2}x_{i_2} = y$,因为$y$给定,发现就是一个二维平面里的直线,我们只需要将所有$y=1$和$y=-1$的点分类,能不能确定$w_1$和$w_2$使得所有点的值都等于$-1$或者$1$,即$<0$或者$>0$而等于$0$的情况相当于就是一条直线,将两类点分开。所以转换一下就是求两个凸包是否相交。
三、AC代码
1 #include <bits/stdc++.h>
2
3 using namespace std;
4 #define ll long long
5 #define Min(a,b) ((a)>(b)?(b):(a))
6 #define Max(a,b) ((a)>(b)?(a):(b))
7 #define P pair<int, int>
8 const double EPS = 1e-8;
9 const int MAXN = 1e2+13;
10 const int INF = 1e5;
11
12 //带误差比较,返回x是否等于y
13 inline bool dcmp(double x, double y = 0)
14 {
15 return fabs(x - y) <= EPS;
16 }
17
18 //向量
19 //需要使用一个原点到(x,y)的有向线段表示
20 typedef struct Vec
21 {
22 double x, y;
23
24 Vec(double x = 0, double y = 0) : x(x),y(y) {}
25
26 //向量相加
27 Vec operator+(const Vec &v) const{
28 return Vec(x + v.x, y + v.y);
29 }
30
31 //向量相减
32 Vec operator-(const Vec &v) const{
33 return Vec(x - v.x, y - v.y);
34 }
35
36 //向量数乘 即向量*数d
37 Vec operator*(double d) const{
38 return Vec(x * d, y * d);
39 }
40
41 Vec operator/(double d) const{
42 return Vec(x / d, y / d);
43 }
44
45 //范数,及长度的平方
46 double norm() const{
47 return x * x + y * y;
48 }
49 }Pt;
50
51 //点乘
52 double dot(const Vec &a, const Vec &b)
53 {
54 return a.x * b.x + a.y * b.y;
55 }
56
57 //叉乘
58 //叉乘可以表示四边形的面积
59 double cross(const Vec &a, const Vec &b)
60 {
61 return a.x * b.y - a.y * b.x;
62 }
63
64 //线段,两个点表示
65 struct Seg
66 {
67 Pt a, b;
68
69 Seg(const Pt &a, const Pt &b) : a(a), b(b) {}
70
71 //线段包含点(点在线段上)
72 //先判断是否叉乘等于 0, 如果等于0表示点在线段所在的直线上
73 //再判断点乘是否小于等于0
74 //小于0表示两向量夹角为180,刚好在线段内,
75 //等于0表示刚好在线段两端
76 bool include(const Pt &p) {
77 return dcmp(cross(a - p, b - p)) && dot(a - p, b - p) <= 0;
78 }
79 };
80
81 //直线,两个点表示
82 struct Line
83 {
84 Pt a, b;
85
86 Line() {} //提供一个不需要参数的构造函数
87 Line(const Pt &a, Pt &b) : a(a), b(b) {}
88
89 //点在直线上
90 bool include(const Pt &p) const {
91 return dcmp(cross(a - p, b - p));
92 }
93
94 //两直线关系
95 // 1 表示两直线相交(1交点)
96 // 0 表示两直线平行(0交点)
97 // -1 表示两直线重合(无数交点)
98 static int relation(const Line &a, const Line &b) {
99 if(a.include(b.a) && a.include(b.b)) return -1;
100 else if(dcmp(cross(a.b - a.a, b.b - b.a))) return 0;
101 else return 1;
102 }
103
104 //求两直线交点(若有一个交点)
105 static Pt intersect(const Line &a, const Line &b) {
106 double s1 = cross(b.a - a.a, b.b - a.a), s2 = cross(b.b - a.b, b.a - a.b);
107 return a.a + (a.b - a.a) * s1 / (s1 + s2);
108 }
109
110 };
111
112 //凸包的交点
113 int n;
114 Pt a[MAXN + 1];
115
116 //凸包极角比较函数
117 inline bool compare(const Pt &a, const Pt &b)
118 {
119 //以第一个点为原点的两个向量
120 Vec va = a - ::a[1], vb = b - ::a[1];
121 double t = cross(va, vb);
122 //t>0 表示b的极角大,b在a的逆时针方向
123 //t<0 表示a的极角大,b在a的顺时针方向
124 //t=0 表示a与b极角相同,则比较长度
125 if(!dcmp(t)) return t > 0;
126 else return va.norm() < vb.norm();
127 }
128
129 //多边形
130 struct Poly
131 {
132 std::vector<Pt> pts;
133
134 //判断点是否在多边形内
135 //射线法,作平行于x轴的线
136 bool include(const Pt &p) const {
137 int cnt = 0;
138 //判断与每条边是否有交点
139 for(size_t i = 0; i < pts.size(); i++) {
140 //枚举相邻两点
141 const Pt &a = pts[i], &b = pts[(i+1)%pts.size()];
142
143 //如果点p在边AB上
144 if(Seg(a, b).include(p)) return true;
145
146 double d1 = a.y - p.y, d2 = b.y - p.y, tmp = cross(a - p, b- p);
147 //如果tmp >= 0 && d1 >= 0 && d2 <= 0 那么点在多边形内会被标记两次
148 //将无法排除点在外面刚好记录两次的情况
149 if( (tmp >= 0 && d1 >= 0 && d2 < 0) || (tmp <= 0 && d1 < 0 && d2 >=0)) cnt++;
150 }
151 //因为点可能刚好在外面与边交于一顶点,那么会判断两次
152 //所以根据判断的次数是否为奇数判断
153 return cnt % 2 == 1;
154 }
155
156 //多边形面积
157
158 bool area() const {
159 double res = 0;
160 for(size_t i = 0; i < pts.size(); i++) {
161 //枚举两个点
162 const Pt &a = pts[i], &b = pts[(i+1) % pts.size()];
163 res += cross(a, b);
164 }
165 return res/2;
166 }
167
168 //求凸包,结果存储在自身pts中
169 void convex() {
170 int id = 1;
171 //找最左下角的点当原点
172 for(int i = 1; i <= n; i++) {
173 if(a[i].x < a[id].x || (a[i].x == a[id].x && a[i].y < a[id].y))
174 id = i;
175 }
176 if(id != 1) std::swap(a[1], a[id]);
177
178 //极角排序
179 std::sort(a + 2, a + n + 1, &compare);
180
181 //扫描
182 pts.push_back(a[1]);
183 for(int i = 2; i <= n; i++) {
184 //比较,如果最后一个点在凸包内,则被弹出
185 while(pts.size() >= 2 && cross(a[i] - pts[pts.size() - 2], pts.back() - pts[pts.size() - 2]) >= 0 )
186 pts.pop_back();
187 pts.push_back(a[i]);
188 }
189 }
190 };
191
192 bool solve(Poly &a, Poly &b)
193 {
194 for(int i = 0; i < b.pts.size(); i++) {
195 if(a.include(b.pts[i]))
196 return false;
197 }
198 for(int i = 0; i < a.pts.size(); i++) {
199 if(b.include(a.pts[i]))
200 return false;
201 }
202 return true;
203 }
204
205 Pt c1[MAXN], c2[MAXN];
206
207 int main()
208 {
209 freopen("input.txt", "r", stdin);
210 // freopen("out.txt", "w", stdout);
211 int T;
212 scanf("%d", &T);
213 while(T--) {
214 int N, x, y, f;
215 scanf("%d", &N);
216 Poly p1, p2;
217 int N1 = 1, N2 = 1;
218 for(int i = 0; i < N; i++) {
219 scanf("%d%d%d", &x, &y, &f);
220 if(f == -1) {
221 c1[N1++] = Pt(x+INF, y+INF);
222 }
223 else {
224 c2[N2++] = Pt(x+INF, y+INF);
225 }
226 }
227 for(int i = 1; i < N1; i++) {
228 a[i] = c1[i];
229 }
230 n = N1 - 1;
231 p1.convex();
232 for(int i = 1; i < N2; i++) {
233 a[i] = c2[i];
234 }
235 n = N2 - 1;
236 p2.convex();
237 // cout << " py1 " << endl;
238 // for(int i = 0; i< p1.pts.size(); i++) {
239 // cout << p1.pts[i].x << " , " << p1.pts[i].y << endl;
240 // }
241 // cout << " py2 " << endl;
242 // for(int i = 0; i< p2.pts.size(); i++) {
243 // cout << p2.pts[i].x << " , " << p2.pts[i].y << endl;
244 // }
245 if(solve(p1, p2)) {
246 puts("Successful!");
247 }
248 else puts("Infinite loop!");
249 }
250 return 0;
251 }
HDU_6590 Code 【凸包】的更多相关文章
- hdu多校第一场 1013(hdu6590)Code 凸包交
题意: 给定一组(x1,x2,y),其中y为1或0,问是否有一组(w1,w2,b),使得上述的每一个(x1,x2,y)都满足x1*w1+x2*w2+b在y=1时大于0,在y=-1时小于0. 题解: 赛 ...
- HDU 6590 Code (判断凸包相交)
2019 杭电多校 1 1013 题目链接:HDU 6590 比赛链接:2019 Multi-University Training Contest 1 Problem Description Aft ...
- Code Chef TSUM2(动态凸包+点分治)
题面 传送门 题解 真是毒瘤随机化算法居然一分都不给 首先这种树上的题目一般想到的都是点分 我们考虑如何统计经过当前点的路径的贡献,设当前点\(u\)在序列中是第\(c\)个,那么一条路径的贡献就是 ...
- Code Chef GEOCHEAT(凸包+旋转卡壳+随机化)
题面 传送门 题解 以下记\(S_i=\{1,2,3,...,i\}\) 我们先用凸包+旋转卡壳求出直径的长度,并记直径的两个端点为\(i,j\)(如果有多条直径随机取两个端点) 因为这个序列被\(r ...
- Code Chef DARTSEGM(计算几何+凸包)
题面 传送门 题解 好眼熟丫-- 一月月赛最后一题--,代码都不用改-- //minamoto #include<bits/stdc++.h> #define R register #de ...
- Google Code Jam Round 1A 2015 解题报告
题目链接:https://code.google.com/codejam/contest/4224486/ Problem A. Mushroom Monster 这题题意就是,有N个时间点,每个时间 ...
- 【BZOJ-1069】最大土地面积 计算几何 + 凸包 + 旋转卡壳
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2707 Solved: 1053[Submit][Sta ...
- 【BZOJ-1670】Building the Moat护城河的挖掘 Graham扫描法 + 凸包
1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 464 Solv ...
- poj1113 凸包
result=对所有点凸包周长+pi*2*L WA了一次,被Pi的精度坑了 以后注意Pi尽可能搞精确一点.Pi=3.14还是不够用 Code: #include<vector> #incl ...
随机推荐
- 实现 MyBatis 流式查询的方法
基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用.如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足 ...
- 使用 js 实现十大排序算法: 桶排序
使用 js 实现十大排序算法: 桶排序 桶排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- js swap array
js swap array ES6 swap array 就地交换 no need let , const [ b, a, ] = [ a, b, ]; // ES6 swap const arr = ...
- MySQL 8.x
MySQL 8.x SQL & NoSQL $ mysql --version # mysql Ver 8.0.21 for osx10.15 on x86_64 (Homebrew) # M ...
- how to remove git commit history
how to remove git commit history 如何删除 GitHub 仓库的历史数据 git filter-branch remove GitHub git commit hist ...
- base 64 bug & encodeURIComponent
base64 bug & encodeURIComponent window.btoa("jëh²H¶�%28"); // "autoskiptoclMjiu&q ...
- shit 环信 IM SDK & IM SDK & web
shit 环信 IM SDK & IM SDK & web 环信 IM SDK, 采坑大全 自己写 UI appkey 是否正确 password 是字符串,不是 数字 HTTPS 是 ...
- 微信公众号 bug
微信公众号 bug web bug refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- C++算法代码——统计数字
题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1109 题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000( ...
- 算法图解:Python笔记代码
二分查找 选择排序 递归 快速排序 广度优先搜索 狄克斯特拉算法 贪婪算法 二分查找 def binary_search(lst,item): low = 0 high = len(lst)-1 wh ...