UVA 361 Cops and Robbers(凸包应用)

UVA 361 Cops and Robbers(凸包应用)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=297

题意:

       有c个警察,r个强盗,和o个市民.他们都用二维平面的一个点表示.如果一个市民被3个警察构成的三角形包围,那么他safe.否则,如果这个市民被3个强盗构成的三角形包围,那么他是robbed. 如果该市民既不在警察包围内也不在强盗包围内,那么它是neither.

       现在要你求每个市民的情况.

分析:

       如果直接暴力枚举所有可能的警察构成的三角形,然后再用每个市民的点去判断是否被包含,那么明显超时.其实有下列结论:

       如果某市民被一个警察构成的三角形包围 充要条件 该市民一定在所有警察构成的凸包内.(在边上也算)

       上面结论同样适用于强盗.所以我们只需要分别求出警察和强盗构成的凸包,然后判断一个市民点在两个凸包内的情况即可.

       注意: 本题只要初始警察的个数>=3,那么就算警察构成的凸包形状是一个点或一条线(n点共点,n点共线), 此时如果市民在该点或线上,就也算市民safe. 但是如果初始警察数<=2的话,直接可以不用求凸包,警察不能包围任何人.(强盗情况也是一样的)

AC代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps=1e-10;
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    return x<0?-1:1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    bool operator==(const Point& rhs)const
    {
        return dcmp(x-rhs.x)==0 && dcmp(y-rhs.y)==0;
    }
    bool operator<(const Point& rhs)const
    {
        return dcmp(x-rhs.x)<0 || (dcmp(x-rhs.x)==0 && dcmp(y-rhs.y)<0);
    }
};
typedef Point Vector;
Vector operator-(Point A,Point B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
bool InSegment(Point P,Point A,Point B)
{
    return dcmp(Cross(A-P,B-P))==0 && dcmp(Dot(A-P,B-P))<=0;
}
bool PointInPolygon(Point p,Point *poly,int n)
{
    int wn=0;
    for(int i=0;i<n;i++)
    {
        if(InSegment(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;
    return false;
}
int ConvexHull(Point *p,int n,Point *ch)
{
    sort(p,p+n);
    n=unique(p,p+n)-p;
    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;
}
/***以上为刘汝佳模板***/

const int maxn=200+5;
Point p1[maxn],ch1[maxn];//警察
Point p2[maxn],ch2[maxn];//强盗
int main()
{
    int c,r,o,kase=0;
    while(scanf("%d%d%d",&c,&r,&o)==3)
    {
        if(c==0&&r==0&&o==0) break;
        printf("Data set %d:\n",++kase);//这句话写到了break上面,一直WA..

        for(int i=0;i<c;i++)
            scanf("%lf%lf",&p1[i].x,&p1[i].y);
        for(int i=0;i<r;i++)
            scanf("%lf%lf",&p2[i].x,&p2[i].y);

        int m1=ConvexHull(p1,c,ch1);
        int m2=ConvexHull(p2,r,ch2);
        for(int i=0;i<o;i++)
        {
            Point p;
            scanf("%lf%lf",&p.x,&p.y);
            if(c>=3 && PointInPolygon(p,ch1,m1))
                printf("     Citizen at (%.0lf,%.0lf) is safe.\n",p.x,p.y);
            else if(r>=3 && PointInPolygon(p,ch2,m2))
                printf("     Citizen at (%.0lf,%.0lf) is robbed.\n",p.x,p.y);
            else
                printf("     Citizen at (%.0lf,%.0lf) is neither.\n",p.x,p.y);
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(Algorithm,算法,ACM,计算几何)