您的位置:首页 > 其它

hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)

2014-08-15 16:54 204 查看
题意:

  在二维平面上,给定n个人

  每个人的坐标和移动速度v

  若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点)

  则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 ,否则输出0

思路:

  1、把所有点按速度排个序,然后把不是最大速度的点去掉

  剩下的点才有可能是占有无穷大的面积

  2、给速度最大的点做个凸包,则只有在凸包上的点才有可能占有无穷大

  若一个位置有多个人,则这几个人都是不能占有无穷大的。

  凸包上边里共线的点是要保留的。

#易错点:

1.凸包边上要保留共线的点,最好采用水平排序(构造凸包前)

  2.对于去重点,必须在构造完凸包之后。

WA:构造凸包之前去重点(构造凸包的点不包括有重复的点)

#include<stdio.h>
#include<algorithm>
#include<fstream>
#include<string.h>
#include<iostream>
using namespace std;
const int MAX=550;
struct point
{
int x;
int y;
int v;
int i;
int tmp;
} Ini[MAX],res[MAX],p[MAX];
bool flag[MAX];
int ans[MAX];
bool cmp(point A,point B)
{
if(A.y==B.y)return A.x<B.x;
return A.y<B.y;
}
bool cmp1(point A,point B)
{
if(A.v>B.v)return true;
if(A.v==B.v)
{
if(A.x<B.x)return true;
if(A.x==B.x&&A.y<B.y)return true;
}
return false;
}
int cross(point A,point B,point C)
{
return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);
}
int Graham(point *p,int n)
{
//if (n<3)return n;
sort(p,p+n,cmp);
memset(flag,false,sizeof(flag));
int i;
int top=0;
for(i=0; i<n; i++)
{
while(top>=2&&cross(res[top-2],res[top-1],p[i])<0)
{
top--;
}
res[top++]=p[i];
res[top-1].tmp=i;
}
for(i=0;i<top;i++)
flag[res[i].tmp]=true;

int t=top+1;
for(i=n-2; i>=0; i--) //i>=0
{
while(top>=t&&cross(res[top-2],res[top-1],p[i])<0)
top--;
if(!flag[i])res[top++]=p[i];
//if(i==0)top--;
}
/*for(i=0; i<top; i++)
printf("$%d %d\n",res[i].x,res[i].y);*/
return top;
}
int main()
{
int n;
int i,j;
//ifstream cin("A.txt");
int __case=0;
while(cin>>n&&n)
{
for(i=0; i<n; i++)
{
cin>>Ini[i].x>>Ini[i].y>>Ini[i].v;
Ini[i].i=i;
}
sort(Ini,Ini+n,cmp1);
//cout<<Ini[i-1].x<<Ini[i-1].y;
int tmp=0;
for(i=0; i<n; i++)
{
if(Ini[0].v>0&&Ini[0].v==Ini[i].v)tmp++;
else break;
}

memset(ans,0,sizeof(ans));
point po;
for(i=0,j=0;i<tmp;i++)
{
po=Ini[i];
//flag=1;
if(i<tmp-1&&Ini[i+1].x==po.x&&Ini[i+1].y==po.y)
{
//flag=0;
while(i<tmp-1&&Ini[i+1].x==po.x&&Ini[i+1].y==po.y)
{
ans[Ini[i].i]=-1;
i++;
}
ans[Ini[i].i]=-1;
}
p[j++]=po;
}
int m=Graham(p,j);

printf("Case #%d: ",++__case);
for(i=0; i<m; i++)
{
if(!ans[res[i].i])ans[res[i].i]=1;
}
for(i=0; i<n; i++)
{
if(ans[i]==1)printf("1");
else printf("0");
}
printf("\n");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: