uva10256 The Great Divide

137 篇文章 0 订阅

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 invited Geta x , the venerable druid of
Asterix ‘s village, to gure out whether such a dividing line exists
or not. Geta x Since Geta x knows that you are so good in programming,
he seeks your help. Input The input may contain multiple test cases.
The rst line of each test case contains two integers M and C (1 M;C
500), indicating the number of houses of the supporters of Majestix
and Cleverdix respectively. Each of the next M lines contains two
integers x and y (

先求出两部分点的凸包,问题就是凸包是否有公共部分【是否相离】。
凸包相交,只需要判断每两条边是否相交。
凸包内含,只需要各取一个点判断是否在另一个多边形里面。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-8;
int cmp(double x)
{
    if (x>eps) return 1;
    if (fabs(x)<eps) return 0;
    return -1;
}
struct vector
{
    double x,y;
    void rd()
    {
        scanf("%lf%lf",&x,&y);
    }
    bool operator < (const vector &v) const
    {
        return cmp(x-v.x)==-1||(cmp(x-v.x)==0&&cmp(y-v.y)==-1);
    }
    bool operator == (const vector &v)
    {
        return cmp(x-v.x)==0&&cmp(y-v.y)==0;
    }
    vector operator + (const vector &v) const
    {
        return (vector){x+v.x,y+v.y};
    }
    vector operator - (const vector &v) const
    {
        return (vector){x-v.x,y-v.y};
    }
    vector operator * (const double &k) const
    {
        return (vector){x*k,y*k};
    }
    vector operator / (const double &k) const
    {
        return (vector){x/k,y/k};
    }
}a[510],b[510],tem[510];
typedef vector point;
double dot(vector v1,vector v2)
{
    return v1.x*v2.x+v1.y*v2.y;
}
double cross(vector v1,vector v2)
{
    return v1.x*v2.y-v1.y*v2.x;
}
struct seg
{
    point a,b;
};
bool onseg(point p,seg s)
{
    return p==s.a||p==s.b||(cmp(dot(s.b-s.a,p-s.a))==0&&cmp(dot(p-s.a,p-s.b))==-1);
}
bool intersect(seg s1,seg s2)
{
    if (onseg(s1.a,s2)||onseg(s1.b,s2)||onseg(s2.a,s1)||onseg(s2.b,s1)) return 1;
    int c1=cmp(cross(s2.b-s2.a,s1.a-s2.a)),c2=cmp(cross(s2.b-s2.a,s1.b-s2.a)),
    c3=cmp(cross(s1.b-s1.a,s2.a-s1.a)),c4=cmp(cross(s1.b-s1.a,s2.b-s1.a));
    return c1*c2==-1&&c3*c4==-1;
}
bool inside(point p,point *a,int n)
{
    int cnt=0;
    for (int i=1;i<n;i++)
    {
        int x=cmp(cross(a[i+1]-a[i],p-a[i])),y=cmp(p.y-a[i].y),z=cmp(p.y-a[i+1].y);
        if (x==1)
        {
            if (y>=0&&z==-1) cnt++;
        }
        else
        {
            if (z>=0&&y==-1) cnt--;
        }
    }
    return cnt;
}
int n,m;
void solve(int n,point *f,int &nn)
{
    for (int i=1;i<=n;i++) tem[i].rd();
    sort(tem+1,tem+n+1);
    n=unique(tem+1,tem+n+1)-tem-1;
    nn=0;
    for (int i=1;i<=n;i++)
    {
        while (nn>1&&cmp(cross(f[nn]-f[nn-1],tem[i]-f[nn-1]))==-1) nn--;
        f[++nn]=tem[i];
    }
    int nnn=nn;
    for (int i=n-1;i;i--)
    {
        while (nn>nnn&&cmp(cross(f[nn]-f[nn-1],tem[i]-f[nn-1]))==-1) nn--;
        f[++nn]=tem[i];
    }
}
bool solve()
{
    int nn,mm;
    solve(n,a,nn);
    solve(m,b,mm);
    for (int i=1;i<nn;i++)
        for (int j=1;j<mm;j++)
            if (intersect((seg){a[i],a[i+1]},(seg){b[j],b[j+1]})) return 0;
    if (inside(a[1],b,mm)||inside(b[1],a,nn)) return 0;
    return 1;
}
int main()
{
    //freopen("in.txt","r",stdin);
    while (scanf("%d%d",&n,&m)&&n)
        if (solve()) printf("Yes\n");
        else printf("No\n");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值