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 Altruistix and peace reigned in the village. But now those happy days are just dreams. The villagers are now divided. Some of the villagers have elected Majestix as their chief and the others have elected Cleverdix.

                        

Majestix                                             Cleverdix

The two chiefs have decided to divide the village into two parts by digging a straight ditch through the middle of the village so that the houses of the supporters of Majestix lie on one part and those of the followers of Cleverdix lie on the other. So, they have invitedGetafix, the venerable druid of Asterix’s village, to figure out whether such a dividing line exists or not.

Getafix

Since Getafix knows that you are so good in programming, he seeks your help.

 

Input

The input may contain multiple test cases.

The first line of each test case contains two integers M and C (1 £ M, C £ 500), indicating the number of houses of the supporters ofMajestix and Cleverdix respectively.

Each of the next M lines contains two integers x and y (-1000 £ x, y £ 1000) giving the co-ordinates of the house of a supporter ofMajestix. For convenience each house is considered as a single point on the plane.

Each of the next C lines contains two integers x and y (-1000 £ x, y £ 1000) giving the co-ordinates of the house of a supporter ofCleverdix.

The input will terminate with two zeros for M and C.

Output

For each test case in the input output a line containing either “Yes” or “No” depending on whether there exists a straight line that divides the two set of houses. The dividing line can NOT contain points of both sides.

 

Sample Input

4 3

100 600

200 400

600 500

300 700

400 100

600 200

500 300

4 3

100 600

400 100

600 200

500 300

200 400

600 500

300 700

0 0

 

Sample Output

Yes

No

判断两个点集是否相交,即有没有一条线段可以划分两个点集。

先求出凸包。

判断凸包中是否有一点在另一个凸包内。

判断凸包内是否有任意两条线段相交。

注意下,按坐标排序的时候要用dcmp来写。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 533 ;
const double eps = 1e-10 ;
int n1 , n2 ;

int dcmp( double x ) { if( fabs(x)<eps) return 0 ; return x<0?-1:1;}

struct Point {
    double x , y ;
    Point(){};
    Point( double a, double b ) { x=a ,y=b; }
    bool operator < ( const Point &a ) const {
        return dcmp(x-a.x)<0 ||(dcmp(x-a.x)==0 && dcmp(y-a.y)<0);
    }

}p1[N],p2[N],ch1[N],ch2[N];
Point operator - ( Point a , Point b ) {
    return Point(a.x-b.x,a.y-b.y);
}
Point operator + ( Point a , Point b ) {
    return Point(a.x+b.x,a.y+b.y);
}
double Cross( Point a , Point b ) { return a.x*b.y-a.y*b.x; }
double Dot( Point a , Point b ) { return a.x*b.x+a.y*b.y; }             //test

bool isPointOnSegment( Point p , Point a1 , Point a2 ) {
    return dcmp( Cross(a1-p,a2-p)) == 0 && dcmp(Dot(a1-p,a2-p)) < 0 ;
}

bool SegmentProperIntersection(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 ;
}

bool isPointInPolygon( Point p , Point* poly , int n ) {
    int wn = 0 ;
    for( int i = 0 ; i < n ; ++i ) {
        if( isPointOnSegment( p , poly[i] , poly[(i+1)%n] ) ) return true;
        int k = dcmp( Cross( poly[(i+1)%n]-poly[i] , p - poly[i] ) );
        int d1 = dcmp( poly[i].y - p.y );
        int d2 = dcmp( poly[(i+1)%n].y - p.y );
        if( k > 0 && d1<= 0 && d2 > 0 ) wn++ ;
        if( k < 0 && d2 <= 0 && d1 > 0 ) wn--;
    }
    if( wn != 0 ) return true;  // inside
    return false;                //outside
}
int ConvexHull(Point *p,int n,Point *ch)
{
    sort(p,p+n);
    int m=0;
    for(int i=0;i<n;i++)
    {
        while(m>1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
    return m;
}
void Run() {
    for( int i = 0 ; i < n1 ; ++i ){
        scanf("%lf%lf",&p1[i].x,&p1[i].y);
    }
    for( int i = 0 ; i < n2 ; ++i ){
        scanf("%lf%lf",&p2[i].x,&p2[i].y);
    }
    int m1 = ConvexHull(p1,n1,ch1), m2 = ConvexHull(p2,n2,ch2);
    for( int i = 0 ; i < m1 ; ++i )
        if( isPointInPolygon(ch1[i],ch2,m2) ) { puts("No"); return ;}
    for( int i = 0 ; i < m2 ; ++i )
        if( isPointInPolygon(ch2[i],ch1,m1) ) { puts("No"); return ;}
    for( int i = 0 ; i < m1 ; ++i ) {
        for( int j = 0 ; j < m2 ; ++j ){
            if( SegmentProperIntersection( ch1[i],ch1[(i+1)%m1],ch2[j],ch2[(j+1)%m2]) ){
                puts("No"); return ;
            }
        }
    }
    puts("Yes");
}

int main(){
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
    while( scanf("%d%d",&n1,&n2) ==2 && n1 )Run();
}

时间: 2024-10-09 19:22:44

UVA 10256 The Great Divide(凸包划分)的相关文章

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 (判断凸包相交)

题目链接: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 (凸包,多边形的位置关系)

题目链接: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

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

UVA 10375 Choose and divide(数论)

The binomial coefficient C(m,n) is defined as m! C(m,n) = -------- n!(m-n)! Given four natural numbers p, q, r, and s, compute the the result of dividing C(p,q) by C(r,s). The Input Input consists of a sequence of lines. Each line contains four non-n

【暑假】[数学]UVa 10375 Choose and divide

UVa 10375 Choose and divide 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19601 思路: maxn=10000 如果计算maxn!再保存的话显然装不下. 但答案由阶乘的积或商组成,所以可以用唯一分解定理求解.大题思路就是把目前答案的质因子的指数用数组e保存,乘除都对e操作. 需要注意的是筛法求素数优化后的写法. 代码: 1 #include<iostream> 2 #include

UVA 10375 Choose and divide(唯一分解定理)

这么大数的乘法.除法运算,肯定不能先全部乘起来,我的思路是计算出分子.分母上的每个数的个数(因为最大的数为10000,可以开一个数组记录个数). 利用了随机数方法终于知道错在哪了,中间如果出现连乘还是会溢出,这点没想到,以下是我的溢出代码: #include<stdio.h> #include<math.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<

Aizu 1298,UVA 10256(凸包相交)

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