题目链接:点击打开链接
题意:在一张地图上有一些人,他们的速度不同。对于一个点,谁到达这个点的时间严格小于其他所有人,这个点就归谁所有,问哪些人所拥有的面积是无限的。
稍加分析可知面积是无限的人就是找出所有速度最大的人,对他们求一个凸包,凸包上的人都是无限的。
坑有这样几个:
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; }