hdu4946 Area of Mushroom 凸包

题意:无穷大的平面区域,在一定坐标范围内有n个人,每个人有所在的坐标位置和速度,如果针对区域里的某个点,其中一个人到这个点的时间比所有剩下的人各自到这个点都短的话(严格小于),则这个点归这个人掌控。现问,是否每个人掌控的区域面积为无穷大,无穷输出1,否则0。

思路:比赛的时候思路很碎,一开始是分析出,假如有两个人不同速度不同坐标的话,速度大的人必定掌控无限的区域,把速度小的人的区域包裹起来,那么这个问题转化为求速度最大的人。

速度最大的人有多个的时候,乍一看好像是每个人都能掌控无限面积的区域,但是如果遇到5个点构成十字形(形如(1,1),(1,0),(0,1),(1,2),(2,1))或者八叉形((1,1),(0,0),(0,2),(2,2),(2,0)),中间的那个人的掌控的区域肯定是有限的,那么这里开始好像变成了一个凸包问题,不在外围的点肯定区域有限。

假设1个点在凸包边上,它与边的两个端点各自掌控区域的分界线是它分别和两点构成的连线的垂直平分线,显然这两条垂直平分线是平行的,中间夹的区域是边上这点的区域,是个无限的区域,如果这个点不在边上,而是在凸包内部,则两条垂直平分线不平行,相交于某一点,则这点的掌控区域必定有限。

所以这个问题就成了求最大速度点的凸包,注意去重点,有重点的点,没有掌控区域,必定有限。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
int vis[510];
struct Point
{
    int id,v;
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
    bool operator < (const Point& a) const
    {
        if(x==a.x) return y<a.y;
        return x<a.x;
    }
}all[510],m[510],ch[510];
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;
}
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;
}

int main()
{
//    freopen("in.txt","r",stdin);
    int max1,n,cas=0,len,mark;
    while(scanf("%d",&n)&&n)
    {
        max1=-1;
        len=0;
        memset(vis,-1,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%d",&all[i].x,&all[i].y,&all[i].v);
            if(all[i].v>max1)
            {
                max1=all[i].v;
            }
        }
        for(int i=0;i<n;i++)
        {
            mark=0;
            if(all[i].v==max1)
            {
                for(int j=0;j<len;j++)
                {
                    if( m[j].x == all[i].x && m[j].y == all[i].y )
                    {
                        vis[m[j].id]=0;
                        mark=1;
                        break;
                    }
                }
                if(!mark)
                {
                    m[len].id=i;
                    m[len].x=all[i].x;
                    m[len].y=all[i].y;
                    len++;
                }
            }
        }
        int cnt=ConvexHull(m,len,ch);
        for(int i=0;i<cnt;i++)
        {
            int mmm=ch[i].id;
            if(vis[mmm]==-1)
                vis[mmm]=1;
        }
        printf("Case #%d: ",++cas);
        if(max1==0)
        {
            for(int i=0;i<n;i++)
            {
                printf("0");
            }
        }
        else
        for(int i=0;i<n;i++)
        {
            if(vis[i]==-1) vis[i]=0;
            printf("%d",vis[i]);
        }
        cout<<endl;
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值