UVA 10256 The Great Divide (判断凸包相交)
时间:2019-08-21
本文章向大家介绍UVA 10256 The Great Divide (判断凸包相交),主要包括UVA 10256 The Great Divide (判断凸包相交)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目链接:UVA 10256
题意
有n个红点和m个蓝点,问是否存在一条直线能够分开红点和蓝点。
题解
分别求出红点和蓝点的凸包,判断两个凸包是否相交。
凸包不相交的条件:
- 凸包上的任意点都在另一个凸包的外面
- 凸包的任意线段都与另一个凸包不相交
代码
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
class Point {
public:
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
Point operator+(Point a) {
return Point(a.x + x, a.y + y);
}
Point operator-(Point a) {
return Point(x - a.x, y - a.y);
}
bool operator<(const Point &a) const {
if (x == a.x)
return y < a.y;
return x < a.x;
}
bool operator==(const Point &a) const {
if (fabs(x - a.x) < eps && fabs(y - a.y) < eps)
return 1;
return 0;
}
double length() {
return sqrt(x * x + y * y);
}
};
typedef Point Vector;
double cross(Vector a, Vector b) {
return a.x * b.y - a.y * b.x;
}
double dot(Vector a, Vector b) {
return a.x * b.x + a.y * b.y;
}
bool isclock(Point p0, Point p1, Point p2) {
Vector a = p1 - p0;
Vector b = p2 - p0;
if (cross(a, b) < -eps)
return true;
return false;
}
double getDistance(Point a, Point b) {
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
typedef vector<Point> Polygon;
Polygon Andrew(Polygon s) {
Polygon u, l;
if(s.size() < 3) return s;
sort(s.begin(), s.end());
u.push_back(s[0]);
u.push_back(s[1]);
l.push_back(s[s.size() - 1]);
l.push_back(s[s.size() - 2]);
for(int i = 2 ; i < s.size() ; ++i) {
for(int n = u.size() ; n >= 2 && !isclock(u[n - 2], u[n - 1], s[i]); --n) {
u.pop_back();
}
u.push_back(s[i]);
}
for(int i = s.size() - 3 ; i >= 0 ; --i) {
for(int n = l.size() ; n >=2 && !isclock(l[n-2],l[n-1],s[i]); --n) {
l.pop_back();
}
l.push_back(s[i]);
}
for(int i = 1 ; i < u.size() - 1 ; i++) l.push_back(u[i]);
return l;
}
int dcmp(double x) {
if (fabs(x) <= eps)
return 0;
return x > 0 ? 1 : -1;
}
// 判断点在线段上
bool OnSegment(Point p, Point a1, Point a2) {
return dcmp(cross(a1 - p, a2 - p)) == 0 && dcmp(dot(a1 - p, a2 - p)) < 0;
}
// 判断线段相交
bool Intersection(Point a1, Point a2, Point b1, Point b2) {
double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1),
c3 = cross(b2 - b1, a1 - b1), c4 = cross(b2 - b1, a2 - b1);
return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}
// 判断点在凸包内
int isPointInPolygon(Point p, vector<Point> s) {
int wn = 0, cc = s.size();
for (int i = 0; i < cc; i++) {
Point p1 = s[i];
Point p2 = s[(i + 1) % cc];
if (p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1;
int k = dcmp(cross(p2 - p1, p - p1));
int d1 = dcmp(p1.y - p.y);
int d2 = dcmp(p2.y - p.y);
if (k > 0 && d1 <= 0 && d2 > 0) wn++;
if (k < 0 && d2 <= 0 && d1 > 0) wn--;
}
if (wn != 0) return 1;
return 0;
}
void solve(Polygon s1, Polygon s2) {
int c1 = s1.size(), c2 = s2.size();
for(int i = 0; i < c1; ++i) {
if(isPointInPolygon(s1[i], s2)) {
printf("No\n");
return;
}
}
for(int i = 0; i < c2; ++i) {
if(isPointInPolygon(s2[i], s1)) {
printf("No\n");
return;
}
}
for (int i = 0; i < c1; i++) {
for (int j = 0; j < c2; j++) {
if (Intersection(s1[i], s1[(i + 1) % c1], s2[j], s2[(j + 1) % c2])) {
printf("No\n");
return;
}
}
}
printf("Yes\n");
}
int main() {
int n, m;
while (cin >> n >> m) {
if(n == 0 && m == 0) break;
Polygon s1, s2;
for (int i = 0; i < n; ++i) {
double x1, x2;
scanf("%lf%lf", &x1, &x2);
s1.push_back(Point(x1, x2));
}
for (int i = 0; i < m; ++i) {
double x1, x2;
scanf("%lf%lf", &x1, &x2);
s2.push_back(Point(x1, x2));
}
if(s1.size()) s1 = Andrew(s1);
if(s2.size()) s2 = Andrew(s2);
solve(s1, s2);
}
return 0;
}
参考
原文地址:https://www.cnblogs.com/wulitaotao/p/11391803.html
- CSS魔法堂:Box-Shadow没那么简单啦:)
- java操作redis: 将string、list、map、自定义的对象保存到redis中
- 运行第一个Docker容器-Docker for Web Developers(1)
- 手动实现jQuery Tools里面tab功能
- Angular企业级开发(9)-前后端分离之后添加验证码
- 基于thrift的微服务框架
- Sublime Text 快速格式化
- HTML中拖放介绍
- 打造高效前端工作环境 - tmux
- 基于thrift的微服务框架
- thrift中的超时(timeout)坑
- 基于webmagic的爬虫项目经验小结
- Docker Hub工作流程-Docker for Web Developers(6)
- PHP+MySQL代码部署在Linux(Ubuntu)上注意事项
- 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 数组属性和方法
- 从JVM设计者的角度来看.class文件结构,一文弄懂.class文件的身份地位
- 抓包分析UDP,TCP和UDP的区别说不上五条就进来看看吧
- 学习|C#线程中AutoResetEvent的使用
- Httprouter—用go实现的高性能路由器
- Django-python最流行的web框架
- C++ 类的不同构造与三种引用
- C++继承、虚函数、RTTI、友元类、异常处理
- C++基本语法
- 抓包分析TCP三次握手四次挥手全过程,教你观看“多包运动”的正确姿势
- 抓包分析以太网帧和IP数据包,头部那么多东东用来干啥的,扫盲篇
- 一文洞悉 OSI和TCP/IP模型,理通所有协议,再也不用似懂非懂了
- 图解https演变以及各种加密解密过程一篇就够!(通俗易懂白话文)
- vs code 创建vue模版
- WebAssembly如何演进成为“浏览器第二编程语言”?
- SAP ABAP和Java的动态代理实现