题意:无穷大的平面区域,在一定坐标范围内有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;
}