Aizu 1298,UVA 10256(凸包相交)

给两类点,问是否存在一条直线把两类点划分,满足:1. 直线上没有点;2. 一类点在直线一侧,另一类点在直线另一侧。

这种题嘛,把两类点分别求个凸包,然后判断两个凸包是否有交点就行了。分析下,考虑两个凸包点数都>=3的时候,只需要判断,一,A凸包的点是否在B上或内部,反之要盼,二,是否有A凸包的一个线段和B凸包的一个线段相交。当存在一个凸包点数<=2的时候,会有点麻烦,但可以找到一个简便的方法,不需要讨论太多的方法,来解决。(最坏也就是枚举嘛,点和点,点和直线,点和凸包,直线和直线,直线和凸包,凸包和凸包。在这个基础上节省一下,发现只需要枚举点和点,点和直线,其余和凸包)..

以下是Aizu 1298的 代码,UVA10256那题输出时候字符有点不同。

My Code

//Hello. I‘m Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned int uin;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define MAXN
#define N 510
#define M
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
const double eps=1e-9;
inline int dcmp(double x){
    if(fabs(x)<eps) return 0;
    else if(x<0) return -1;
    else return 1;
}
int n,m;
struct Point{
    double x,y;
    Point(){};
    Point(double xx,double yy){
        x=xx,y=yy;
    }
};
inline bool comp(const Point a,const Point b){
    if(dcmp(a.x-b.x)) return a.x<b.x;
    else return a.y<b.y;
}
typedef Point Vector;
Vector operator+(const Vector a,const Vector b){
    return Vector(a.x+b.x,a.y+b.y);
}
Vector operator-(const Vector a,const Vector b){
    return Vector(a.x-b.x,a.y-b.y);
}
double operator*(const Vector a,const Vector b){
    return a.x*b.x+a.y*b.y;
}
double operator%(const Vector a,const Vector b){
    return a.x*b.y-a.y*b.x;
}
Vector operator*(const Vector a,const double b){
    return Vector(a.x*b,a.y*b);
}
Vector operator*(const double b,const Vector a){
    return Vector(a.x*b,a.y*b);
}
bool operator ==(const Vector a,const Vector b){
    return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);
}
Vector operator/(const Vector a,const double b){
    return Vector(a.x/b,a.y/b);
}
double Square_Triangle(Point p1,Point p2,Point p3){
    //三角形面积(无方向)
    return 0.5*fabs((p2-p1)%(p3-p1));
}
#define lenp res.size()
void Convex_Hull(Point *p,int n,vector<Point>&res){
    res.clear();
    sort(p,p+n,comp);
    for(int i=0;i<n;i++){
        while(lenp>1&&dcmp((res[lenp-1]-res[lenp-2])%(p[i]-res[lenp-1]))<=0) res.pop_back();
        res.push_back(p[i]);
    }
    int k=(int)lenp;
    for(int i=n-2;i>=0;i--){
        while(lenp>k&&dcmp((res[lenp-1]-res[lenp-2])%(p[i]-res[lenp-1]))<=0) res.pop_back();
        res.push_back(p[i]);
    }
    if(lenp>1) res.pop_back();
}
void readPointInt(Point &p){
    int x,y;
    x=read(),y=read();
    p=Point(x,y);
}
Point p1[N],p2[N];
#define lenv1 v1.size()
#define lenv2 v2.size()
#define lenv v.size()
double Square_ConvexHull(vector<Point>&v){//获取凸包的面积
    //lenv>=3
    double res=0.0;
    for(int i=1;i<lenv-1;i++){
        res+=Square_Triangle(v[0],v[i],v[i+1]);
    }
    return res;
}
double Square_PointWithConvexHull(Point p,vector<Point>&v){
    //求一点绕凸包扫一圈形成的面积
    v.push_back(v[0]);
    double res=0.0;
    for(int i=0;i<lenv-1;i++){
        res+=Square_Triangle(p,v[i],v[i+1]);
    }
    v.pop_back();
    return res;
}
bool PointOnSegment(Point p,Point p1,Point p2){
    Vector v1=p1-p,v2=p2-p;
    if(dcmp(v1%v2)) return false;
    else if(dcmp(v1*v2)>0) return false;
    else return true;
}
bool PointInConvexHull1_In_ConvexHull2(vector<Point>&v1,vector<Point>&v2){
    if(lenv1==1&&lenv2==1) return v1[0]==v2[0];
    if(lenv1==1&&lenv2==2) return PointOnSegment(v1[0],v2[0],v2[1]);
    if(lenv2>=3){
        double Sv2=Square_ConvexHull(v2);
        for(int i=0;i<lenv1;i++){
            double St=Square_PointWithConvexHull(v1[i],v2);
            if(!dcmp(St-Sv2)) return true;
        }
    }
    return false;
}
bool Segment1_Inter_Segment2(Point p1,Point p2,Point q1,Point q2){
    if(!dcmp((p1-p2)%(q1-q2))){
        return PointOnSegment(p1,q1,q2)||PointOnSegment(p2,q1,q2)||PointOnSegment(q1,p1,p2)||PointOnSegment(q2,p1,p2);
    }
    else{
        int t1=dcmp((p2-p1)%(q1-p1));
        int t2=dcmp((p2-p1)%(q2-p1));
        int t3=dcmp((q2-q1)%(p1-q1));
        int t4=dcmp((q2-q1)%(p2-q1));
        return t1*t2<=0&&t3*t4<=0;
    }
}
bool ConvexHull1_Inter_ConvexHull2(vector<Point>&v1,vector<Point>&v2){
    //凸包点是否在另一个凸包内
    if(PointInConvexHull1_In_ConvexHull2(v1,v2)) return true;
    if(PointInConvexHull1_In_ConvexHull2(v2,v1)) return true;
    //两凸包线段是否相交
    if(lenv1>=2&&lenv2>=2){
        v1.push_back(v1[0]);
        v2.push_back(v2[0]);
        for(int i=0;i<lenv1-1;i++){
            for(int j=0;j<lenv2-1;j++){
                if(Segment1_Inter_Segment2(v1[i],v1[i+1],v2[j],v2[j+1])){
                    v1.pop_back();
                    v2.pop_back();
                    return true;
                }
            }
        }
        v1.pop_back();
        v2.pop_back();
    }
    return false;
}
int main(){
    while(1){
        n=read(),m=read();
        if(!n&&!m) break;
        for(int i=0;i<n;i++){
            readPointInt(p1[i]);
        }
        vector<Point>res1;
        Convex_Hull(p1,n,res1);
        for(int i=0;i<m;i++){
            readPointInt(p2[i]);
        }
        vector<Point>res2;
        Convex_Hull(p2,m,res2);
        if(ConvexHull1_Inter_ConvexHull2(res1,res2)){
            printf("NO\n");
        }
        else printf("YES\n");
    }
    return 0;
}
时间: 2024-10-09 19:22:48

Aizu 1298,UVA 10256(凸包相交)的相关文章

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:

UVa 10256 The Great Divide,判断两个凸包是否相离

先从给出的两个点集中分别计算出两个凸包, 然后判断两个凸包是否相离. #include<cstdio> #include<vector> #include<cmath> #include<algorithm> using namespace std; const double eps = 1e-10; double dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -

UVA 10256 The Great Divide (凸包,多边形的位置关系)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34148 [思路] 凸包 求出红蓝点的凸包,剩下的问题就是判断两个凸包是否相离. 需要确定两点: 1)  凸包上线段是否相交->相交 2)  凸包上的点是否包含在另一个凸包里->内含. [代码] 1 #include<cmath> 2 #include<vector> 3 #include<cstdio> 4 #include&

UVa 10256 (判断两个凸包相离) The Great Divide

题意: 给出n个红点,m个蓝点.问是否存在一条直线使得红点和蓝点分别分布在直线的两侧,这些点不能再直线上. 分析: 求出两种点的凸包,如果两个凸包相离的话,则存在这样一条直线. 判断凸包相离需要判断这两件事情: 任何一个凸包的任何一个顶点不能在另一个凸包的内部或者边界上. 两个凸包的任意两边不能相交. 二者缺一不可,第一条很好理解,但为什么还要判断第二条,因为存在这种情况: 虽然每个凸包的顶点都在另一个凸包的外部,但两个凸包明显是相交的. 1 //#define LOCAL 2 #include

UVA 10256 The Great Divide(凸包划分)

The Great Divide Input: standard input Output: standard output Time Limit: 8 seconds Memory Limit: 32 MB Somewhere in Gaul, there is a little village very like the village where Asterix and Obelix live. Not very long ago they had only one chief Altru

UVA10256 The Great Divide(凸包相交)

原题链接:UVA10256 The Great Divide 题意:平面上有n个红点和m个蓝点,是否存在一条直线使得任取一个红点和一个蓝点都在直线的异侧?这条直线不能穿过红点或蓝点 分析:显然,求红点凸包和蓝点凸包,如果这两个凸包有相交的部分就不存在这样的直线,否则就存在呗 #include <bits/stdc++.h> using namespace std; double eps=1e-15; double pi=acos(-1); struct Point{ double x,y; P

HDU6590 Code 判断凸包相交

网址:https://vjudge.net/problem/HDU-6590 题意: 找出一条直线使得黑点和白点全部分布在直线的同一侧. 题解: 支持向量机. 对每一类点求凸包,判断凸包是否相交即可. AC代码:挖坑待填. 原文地址:https://www.cnblogs.com/Aya-Uchida/p/11260500.html

uva 10256 The Great Divide

题意:给定两个点集,一个红点集,另一个蓝点集,询问,能否找到一条直线能,使得任取一个红点和蓝点都在直线异侧. 思路:划分成两个凸包,一个红包,一个蓝包.两个凸包不相交不重合. 1.任取一个凸包中的点不在另一个凸包中. 2.任取一个凸包中的边与另一个凸包不相交. 1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostrea

UVa 11168 (凸包+点到直线距离) Airport

题意: 平面上有n个点,求一条直线使得所有点都在直线的同一侧.并求这些点到直线的距离之和的最小值. 分析: 只要直线不穿过凸包,就满足第一个条件.要使距离和最小,那直线一定在凸包的边上.所以求出凸包以后,枚举每个边求出所有点到直线的距离之和得到最小值. 点到直线距离公式为: 因为点都在直线同一侧,所以我们可以把加法“挪”到里面去,最后再求绝对值,所以可以预处理所有点的横坐标之和与纵坐标之和.当然常数C也要记得乘上n倍. 已知两点坐标求过该点直线的方程,这很好求不再赘述,考虑到直线没有斜率的情况,