UVA10256 The Great Divide

Posted cjjsb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA10256 The Great Divide相关的知识,希望对你有一定的参考价值。

怎么又没人写题解,那我来贡献一发好了。

题目意思很简单,平面上有两种颜色的点,问你能否求出一条直线使两种颜色的点完全分开。

首先我们考虑两个点集相离的充要条件,这两个点集的凸包必须相离。(很好证明或者画画图理解一下)

那么怎么判断两个凸包相离,考虑到这里的点的个数不多,我们可以用一种最暴力的方法。

枚举一个凸包上的所有点所有边,然后判断是否与另一个凸包相离即可。

点是否在多边形内?直接暴力转角法即可(不推荐射线法,好理解但不好写,精度不高)

边是否在多边形内,在两个凸包中分别枚举一条边,然后判断是否相交即可。

稍微注意一下精度问题即可,其实计算几何的题主要考验的就是代码的细节能力。

CODE

#include<cstdio>
#include<cmath>
#include<algorithm>
#define RI register int
using namespace std;
typedef double DB;
const int N=505;
const DB EPS=1e-10;
inline int dcmp(DB x)
{
    if (fabs(x)<EPS) return 0; return x<0?-1:1;
}
struct Point
{
    DB x,y;
    Point(DB X=0,DB Y=0) { x=X; y=Y; }
    inline friend bool operator <(Point A,Point B)
    {
        return dcmp(A.x-B.x)<0||(!dcmp(A.y-B.y)&&dcmp(A.y-B.y)<0);
    }
    inline friend bool operator ==(Point A,Point B)
    {
        return !dcmp(A.x-B.x)&&!dcmp(A.y-B.y);
    }
}a[N],b[N],cov_a[N],cov_b[N]; int n,m,cnt_a,cnt_b; DB x,y;
typedef Point Vector;
inline Vector operator -(Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); }
class Computation_Geometry
{
    private:
        inline DB Dot(Vector A,Vector B)
        {
            return A.x*B.x+A.y*B.y;
        }
        inline DB Cross(Vector A,Vector B)
        {
            return A.x*B.y-A.y*B.x;
        }
        inline bool OnSegment(Point p,Point A,Point B)
        {
            return !dcmp(Cross(A-p,B-p))&&dcmp(Dot(A-p,B-p))<0;
        }
        inline bool IsPointInPolygon(Point p,Point *a,int n)
        {
            int t=0; for (RI i=1;i<=n;++i)
            {
                Point p1=a[i],p2=a[(i+1)%n+1];
                if (p1==p||p2==p||OnSegment(p,p1,p2)) return 1;
                int ret=dcmp(Cross(p2-p1,p-p1)),d1=dcmp(p1.y-p.y),d2=dcmp(p2.y-p.y);
                if (ret>0&&d1<=0&&d2>0) ++t; if (ret<0&&d2<=0&&d1>0) --t;
            }
            return t!=0;
        }
        inline bool SegmentProperIntersection(Point A,Point B,Point C,Point D)
        {
            DB c1=Cross(B-A,C-A),c2=Cross(B-A,D-A),c3=Cross(D-C,A-C),c4=Cross(D-C,B-C);
            return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
        }
    public:
        inline int ConvexHull(Point *a,int n,Point *p)
        {
            sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1; RI i,top=0;
            for (i=1;i<=n;++i)
            {
                while (top>1&&dcmp(Cross(p[top]-p[top-1],a[i]-p[top]))<=0) --top;
                p[++top]=a[i];
            }
            int t=top; for (i=n-1;i;--i)
            {
                while (top>t&&dcmp(Cross(p[top]-p[top-1],a[i]-p[top]))<=0) --top;
                p[++top]=a[i];
            }
            if (n>1) --top; return top;
        }
        inline bool ConvexPolygonDisjoint(Point *a,int n,Point *b,int m)
        {
            RI i,j; for (i=1;i<=n;++i) if (IsPointInPolygon(a[i],b,m)) return 1;
            for (i=1;i<=m;++i) if (IsPointInPolygon(b[i],a,n)) return 1;
            for (i=1;i<=n;++i) for (j=1;j<=m;++j)
            if (SegmentProperIntersection(a[i],a[i%n+1],b[j],b[j%m+1])) return 1;
            return 0;
        }
}G;
int main()
{
    while (scanf("%d%d",&n,&m),n&&m)
    {
        RI i; for (i=1;i<=n;++i) scanf("%lf%lf",&x,&y),a[i]=Point(x,y);
        for (i=1;i<=m;++i) scanf("%lf%lf",&x,&y),b[i]=Point(x,y);
        cnt_a=G.ConvexHull(a,n,cov_a); cnt_b=G.ConvexHull(b,m,cov_b);
        puts(G.ConvexPolygonDisjoint(cov_a,cnt_a,cov_b,cnt_b)?"No":"Yes");
    };
    return 0;
}

以上是关于UVA10256 The Great Divide的主要内容,如果未能解决你的问题,请参考以下文章

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

UVA10256 The Great Divide

UVA1045 The Great Wall Game

uva1336 Fixing the Great Wall

Fixing the Great Wall UVA - 1336(区间dp)

UVa 1336 Fixing the Great Wall (区间DP)