题目链接:点击打开链接
题意:在一张地图上有一些人,他们的速度不同。对于一个点,谁到达这个点的时间严格小于其他所有人,这个点就归谁所有,问哪些人所拥有的面积是无限的。
稍加分析可知面积是无限的人就是找出所有速度最大的人,对他们求一个凸包,凸包上的人都是无限的。
坑有这样几个:
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;
}
本文介绍了一种计算地图上人物无限拥有的面积问题的解决方案,通过寻找速度最快的人物并利用andrew算法求解凸包来确定无限面积的所有者。
679

被折叠的 条评论
为什么被折叠?



