SGU 253 log(n)判点在凸包内 二分
来源:互联网 发布:json html 示例输出 编辑:程序博客网 时间:2024/05/21 08:56
水平序和极角序都可以,极角序相对方便
用极角序的,直接二分就可以了。
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long ll;const double eps = 1e-8;const int maxn = 100005;struct Point { double x, y;}p[maxn];int n, m, k;double cross(Point o, Point a, Point b) { return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);}bool binary(Point *p, Point &tp) {//条件:p点集必须是顺时针或者逆时针//(注意3点共线下的点也必须满足这个条件)//(如果有3点共线极角序不能完成该条件) int l = 0, r = n-1; while(l < r) { int m = l+r >> 1; int c1 = cross(p[0], p[m], tp); int c2 = cross(p[0], p[(m+1)%n], tp); int c3 = cross(p[m], p[(m+1)%n], tp); if(c1 >= 0 && c2 <= 0 && c3 >= 0) return true; if(c1 >= 0) l = m+1; else r = m; } return false;}int main() { int i; scanf("%d%d%d", &n, &m, &k); for(i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y); int cnt = 0; p[n] = p[0]; while(m--) { Point tp; scanf("%lf%lf", &tp.x, &tp.y); cnt += binary(p, tp); } if(cnt >= k) puts("YES"); else puts("NO"); return 0;}
用水平序做的,我的做法还要对点排序和求上下凸包,
还是写搓了,不想写极角序了。
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define LL __int64int n, m, k;struct point {int x, y;void in() {scanf("%d%d", &x, &y);}bool operator < (const point &t) const{ return y < t.y || (y == t.y && x < t.x);}bool operator == (const point &t) const { return x == t.x && y == t.y;}}p[100005];LL cross(point o, point a, point b) {return (LL)(a.x-o.x)*(b.y-o.y)-(LL)(a.y-o.y)*(b.x-o.x);}point up[100005], down[100005]; // 水平序后的上下凸包int top, sum1, sum2;void convex() {top = 0;int i, j;for(i = 0; i < n; i++) {while(top >= 2 && cross(down[top-2], down[top-1], p[i]) < 0) top--;down[top++] = p[i];}sum2 = top;top = 0;for(i = n-1; i >= 0; i--) {while(top >= 2 && cross(up[top-2], up[top-1], p[i]) < 0) top--;up[top++] = p[i];}sum1 = top;reverse(up, up+sum1); // 为了后面的lower_bound}int main() {int i, j;scanf("%d%d%d", &n, &m, &k);for(i = 0; i < n; i++) p[i].in();sort(p, p+n);convex();int cnt = 0;while(m--) {point tp;tp.in();if(tp == p[0] ) { cnt++; continue; } // 注意最左下角的点要特判int j = lower_bound(up, up+sum1, tp) - up-1; //找点tp在点j和点j+1之间if(j >= sum1-1 || j < 0) continue;bool g1 = cross(up[j], up[j+1], tp) <= 0;j = lower_bound(down, down+sum2, tp) - down-1; //找点tp在点j和点j+1之间if(j >= sum2-1 || j < 0) continue;bool g2 = cross(down[j], down[j+1], tp) >= 0;if(g1 && g2) cnt++;}if(cnt >= k) puts("YES");else puts("NO");return 0;}
- SGU 253 log(n)判点在凸包内 二分
- 判点是否在凸包内(二分极角序)
- SGU 124 判点在多边形内外边界
- SGU 253 判断点在凸包内
- SGU 253 计算几何 判定点是否在凸包内
- codeforces 366D 求1-n点最大区间长度 枚举区间左端+二分区间右端dfs判可行
- hdu5424 Rikka with Graph II(n个点n条边的图判哈密顿通路)
- 拦截导弹(文件名:missile.c/cpp/pas)[O(n*log(n)),二分优化]
- POJ 2942 Knights of the Round Table (点-双连通分量 + 交叉法染色判二分图)
- hdu 4885 (n^2*log(n)判断三点共线建图)+最短路
- SGU 531 Bonnie and Clyde(二分)
- SGU 154 Factorial(数论+二分)
- SGU 114 Telecasting station(二分)
- SGU 124. Broken line(射线法判断一个点是否在一个多边形内)
- 旋转数组的最小数字(剑指offer 二分 O(log n))
- A 判二分图
- sgu Theodore Roosevelt【判断点是否在凸多边形内模板】
- LIS 的 n*log 算法 ———二分维护
- Visual C++ Debugging: How to use 'ASSERT' and deal with assertions failures?
- 利用[JQuery插件]___验证用户输入到文本框信息。
- E/OMXCodec( 255): [OMX.google.amrnb.encoder]出错问题分析
- Android之Adapter用法总结
- 使用tomcat日志对访问ip进行排序
- SGU 253 log(n)判点在凸包内 二分
- 视图定义、作用、语法及操作
- 杭电2039
- vi命令大全
- 小算法总结一下
- ExecuteNonQuery方法和ExecuteScalar方法和ExecuteReader方法的区别
- 同一段C++在Linux和windows下编译后的可执行文件有什么不同?
- DFS&&BFS Search Graph
- 基于Tiny6410的LED驱动程序