hdu 4946 Area of Mushroom

题目链接:点击打开链接


题意:在一张地图上有一些人,他们的速度不同。对于一个点,谁到达这个点的时间严格小于其他所有人,这个点就归谁所有,问哪些人所拥有的面积是无限的。


稍加分析可知面积是无限的人就是找出所有速度最大的人,对他们求一个凸包,凸包上的人都是无限的。

坑有这样几个:

1.最大速度如果是0,那么所有人的面积都不是无限的。因为要求必须能到达一点才能拥有它。

2.输入会有多个人在同一点的情况,这样这些人的面积都是0,因为到达一点的时间需要严格小于其他人。


还有一点是如果两个人在同一点但是速度不相同是没有影响的,应该先找出所有速度最大的点,再找到那些相同的只留下一个,用这些点求凸包,比赛时先判断了位置而不是速度,wa了n次。


andrew算法求凸包,如果保证输入的点没有重合点的话,把cross()<=0,m--改为cross()<0就可以保留凸包边上的点。如果有重合点会出错。


代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int N;
char res[1010];
struct node{
    int x,y,v,id,vis;
    node(){}
    node(int x,int y):x(x),y(y){}
    bool operator ==(node obj){
        return x==obj.x&&y==obj.y;
    }
    void operator =(node obj){
        x=obj.x;
        y=obj.y;
        v=obj.v;
        id=obj.id;
        vis=obj.vis;
    }
};
typedef node point;

point a[1010];
point b[1010];
point c[1010];
point operator -(point a,point b){
    return point(a.x-b.x,a.y-b.y);
}

int cross(point a,point b){
    return a.x*b.y-b.x*a.y;
}

int cmp1(point a,point b){
    if(a.v==b.v) return a.x<b.x||(a.x==b.x&&a.y<b.y);
    return a.v>b.v;
}

int convexhull(point a[],point b[],int len){
    int m=0;
    sort(a,a+len,cmp1);
    for(int i=0;i<len;i++){
        while(m>1&&cross(b[m-1]-b[m-2],a[i]-b[m-2])<0){
            m--;
        }
        b[m++]=a[i];
    }
    int k=m;
    for(int i=len-2;i>=0;i--){
        while(m>k&&cross(b[m-1]-b[m-2],a[i]-b[m-2])<0){
            m--;
        }
        b[m++]=a[i];
    }
    if(len>1)m--;
    return m;
}
void init(){
    for(int i=0;i<N;i++){
        res[i]='0';
        b[i].vis=0;
        a[i].vis=0;
    }
    res[N]='\0';
}

int main(){
    int cas=1;
    while(cin>>N,N){
        init();
        int vmax=0;
        for(int i=0;i<N;i++){
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
            a[i].id=i;
            vmax=max(vmax,a[i].v);
        }
        if(vmax==0){
            printf("Case #%d: %s\n",cas++,res);
            continue;
        }
        sort(a,a+N,cmp1);
        int len=0;
        int i=0;
        while(i<N){
            if(a[i].v!=vmax) break;
            int l=1;
            while(i+l<N&&a[i]==a[i+l]){
                if(a[i+l].v!=vmax) break;
                l++;
            }
            b[len]=a[i];
            if(l>=2)
                b[len].vis=1;
            len++;
            i+=l;
        }
        int k=convexhull(b,c,len);
        for(int j=0;j<k;j++){
                if(c[j].vis)continue;
                res[c[j].id]='1';
        }
        printf("Case #%d: %s\n",cas++,res);
    }
    return 0;
}






你可能感兴趣的:(凸包)