题目链接
这个题终于让我知道了什么是凸包…
注意的点
1.只用考虑速度最大的人,因为只要
vi<vj
,在无穷远处,必然是
tj<ti
2.如果最大速度为0,那么所有答案均为0,每个人不能移动,所以不可能负责无限的区域。
3.如果两点速度相同并且位置相同,则均为0。
4.对速度最大的点进行凸包,围在里面的点不能到达无穷的区域,只有在边界上的点才行。
3.在进行进行凸包之前不能剔除那些速度最大且位置相同的点,虽然他们答案一定是0,因为如果剔除了,有些本该围在凸包内的点就成了外围点,本来答案是0的点就成了1。
4.凸包边界上如果存在3点共线的情况这个题是需要保留中间点的,但是凸包模板上没有保留,之前我直接将叉乘<=0改为<0,意思是只有在右边时,栈才会弹出元素,如果共线不会弹出。结果这样做是完全错误的。因为这样可能形成的不是凸包,而是“凹包”,因为如果栈中栈顶上的两个点位置相同,那么叉积自然为0,所以就可以随便放东西进去,这样很可能就成了一个凹多边形。
5.正确的方法是,先进行凸包,删除共线的点,然后对所有速度最大并且没有点与之位置相同的点进行检测,看它是否在凸包的边界上,如果是答案为1,否则为0。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
#define sqr(x) ((x)*(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 500 ;
const double PI=acos(-1.0);
const double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}
struct Point
{
double x,y;int v,id;
Point(double x=0,double y=0):x(x),y(y) {};
bool operator ==(const Point B)const {return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;}
bool operator<(const Point& b)const
{
return dcmp(x-b.x)<0|| dcmp(x-b.x)==0 &&dcmp(y-b.y)<0;
}
};
bool cmp(Point a,Point b)//这个排序很实用,现将速度从大到小排,方便处理,同时将位置靠近的排在一起。
{
if(a.v==b.v) return dcmp(a.x-b.x)<0|| dcmp(a.x-b.x)==0 &&dcmp(a.y-b.y)<0;
return a.v>b.v;
}
typedef Point Vector;
Vector operator -(Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y); }
double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x;}
double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;}
bool OnSegment(Point p,Point a1,Point a2)
{
return dcmp(Cross(a1-p,a2-p) )==0&&dcmp(Dot(a1-p,a2-p) )<=0;
}
int n,npo2;Point po[maxn+10],po2[maxn+10],chp[2*maxn+10];bool no[maxn+10],ans[maxn+10];
void ConvexHell(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-1] )<=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-1] )<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
for0(i,npo2)
{
if(no[po[i].id ]) continue;
bool ok=false;
for(int j=0;j<m&&!ok;j++)
{
if(OnSegment(po[i],ch[j],ch[(j+1)%m])) ok=true;
}
if(ok) ans[po[i].id ]=1;
}
// return m;
}
bool same(Point & a,Point b)
{
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
int main()
{
std::ios::sync_with_stdio(false);
int kase=0;
while(cin>>n&&n)
{
mes(no,0,n);mes(ans,0,n);
for0(i,n) {cin>>po[i].x>>po[i].y>>po[i].v;po[i].id=i;}
sort(po,po+n,cmp);
int t;
for(t=1;t<n;t++)
{
if(po[t-1].v!=po[t].v) break;
if(same(po[t-1],po[t])) no[po[t].id ]=no[po[t-1].id ]=1;
}
if(po[0].v==0) t=0;
for0(i,t) po2[i]=po[i];
npo2=t;
ConvexHell(po2,npo2,chp);
printf("Case #%d: ",++kase);
for0(i,n)
{
if(ans[i]) putchar('1');
else putchar('0');
}putchar('\n');
}
return 0;
}