HDU 4946 Area of Mushroom 凸包 第八次多校

来源:互联网 发布:mac网页图片显示问号 编辑:程序博客网 时间:2024/04/30 01:42
题目链接:hdu 4946

题意:一大神有N个学生,各个都是小神,大神有个二次元空间,每个小神都有一个初始坐标,现在大神把这些空间分给徒弟们,规则是如果这个地方有一个人比谁都先到这,那么这个地方就是他的,问谁的地盘面积是无穷大的.

思路:因为空间是无限大的,所以只要速度最大就有可能有无限的地盘,重合的点不能严格的比对方快,也不符合规定,然后求速度最大的点围城的凸包,凡是在凸包上的点且不重合的,地盘都是无穷大.

比赛的时候,不会凸包的,现找的模板,不了解性能,不知道计算凸包不能传重合的点进去结果WA出翔


#include <cstdio>#include <cstring>#include <iostream>#include <cmath>#include <queue>#include <vector>#include <algorithm>#define INF 1e9#define maxn 1000#define EPS 1e-6#define N 1000using namespace std;struct point{    int x,y;  //横纵坐标 : x,y    double len,theta;  //与参考点的距离 len 与参考点构成的向量与 (1,0)向量构成的夹角的余弦值 theta}g[N]; //定义了一个全局变量,记录凸包中的点/*--------按余弦值,从大到小快速排序--------*/void qsort(int st,int en){    int i=st,j=en;    g[0]=g[i];    while(i<j)    {        while(i<j && g[0].theta>=g[j].theta) j--;        if(i<j) { g[i]=g[j]; i++; }        while(i<j && g[0].theta<=g[i].theta) i++;        if(i<j) { g[j]=g[i]; j--; }    }    g[i]=g[0];    if(st<i-1) qsort(st,i-1);    if(i+1<en) qsort(i+1,en);}/*-----------Graham 扫描法-------------*/void graham(int *n){    /*第一步,寻找y坐标最小,然后x坐标最小的点*/    int p=1;    for(int i=2;i<=*n;i++)      if((g[i].y<g[p].y)||(g[i].y==g[p].y && g[i].x<g[p].x)) p=i;    g[0]=g[p]; g[p]=g[1]; g[1]=g[0];    /*找到该点,并把它存放在 g 中的第一个元素的位子上*/        /*第二步,计算所有的点距离参考点的距离(len) 还有夹角的余弦值 (theta)*/    for(int i=2;i<=*n;i++)    {        g[i].len=sqrt((g[i].x-g[1].x)*(g[i].x-g[1].x)+(g[i].y-g[1].y)*(g[i].y-g[1].y));        g[i].theta=100*(g[i].x-g[1].x)/g[i].len;    }    qsort(2,*n);//先根据夹角的余弦值从大到小排序        /*第三步,将所有theta值相等的点,只保存len值最大的,存放在数组map中*/    point map[N];    int tot=0; p=1;    while(p<=*n)    {        int k=p;        while(fabs(g[p].theta-g[p+1].theta)<=EPS)        {            if(g[p+1].len>g[k].len) k=p+1;            p++;        }        map[++tot]=g[k];        p++;    }        /*第四步,对map中的元素扫描一遍,确定凸包的元素,放在数组g中*/    *n=tot; tot=3; //先做了一个小小的处理,使得自己更好理解    memset(g,0,sizeof(g));    g[1]=map[1]; g[2]=map[2]; g[3]=map[3]; //先将前三个点入栈 g     for(int i=4;i<=*n;i++)  //依次用map中的每个点对g中的点进行一次判断,看是否是属于凸包    {        double chaji=(g[tot].x-g[tot-1].x)*(map[i].y-g[tot].y)-(map[i].x-g[tot].x)*(g[tot].y-g[tot-1].y);        for(;chaji<=0 && tot>=1;) //如果旋转的方向不同,g[tot]这个点就不是,删除,并继续判断 g 中下一个点是不是        {            tot--;            chaji=(g[tot].x-g[tot-1].x)*(map[i].y-g[tot].y)-(map[i].x-g[tot].x)*(g[tot].y-g[tot-1].y);        }        g[++tot]=map[i]; //将map[i]这个点入栈,至于是否是属于凸包中的点,等待以后的点来判断    }    *n=tot;//凸包处理完,总共有tot个凸包上的点}/*---------------------------------------------------------------------------------------------*/struct Node{int x,y,v,rank,bl;}tmp;int maxe;vector<Node> stu;int cas=0;bool cmp(Node a,Node b){return a.rank<b.rank;}void init(int n){stu.clear();maxe=0;for(int i=0;i<n;i++){scanf("%d %d %d",&tmp.x,&tmp.y,&tmp.v);tmp.rank=i;tmp.bl=0;stu.push_back(tmp);maxe=max(tmp.v,maxe);}}bool check(int a,int b,int tt){int c;if(b==tt){c=1;}else {c=b+1;} double chaji=(g[c].x-g[b].x)*(stu[a].y-g[c].y)-(stu[a].x-g[c].x)*(g[c].y-g[b].y); if(chaji<=EPS) return 1; else return 0;}int main(){//freopen("data.in","r",stdin);int n;while (~scanf("%d",&n)){if(n==0) break;printf("Case #%d: ",++cas);init(n);if(maxe==0){for(int i=0;i<n;i++){printf("0");}}else {for(int i=0;i<n;i++){if(stu[i].v==maxe){stu[i].bl=1;}}for(int i=0;i<n-1;i++){if(stu[i].bl==1)//错误写法: if(stu[i].v=maxe){for(int j=i+1;j<n;j++){if(stu[i].x==stu[j].x&&stu[i].y==stu[j].y&&stu[i].v==stu[j].v&&i!=j){stu[j].bl=0;stu[i].bl=-1;}}}}int tt=0;for(int i=0;i<n;i++){if(stu[i].v==maxe&&stu[i].bl!=0){g[++tt].x=stu[i].x;g[tt].y=stu[i].y;}}//printf("%d\n",tt);if(tt>=3){graham(&tt);for(int i=0;i<n;i++){if(stu[i].bl==1){stu[i].bl=0;for(int j=1;j<=tt;j++){if((stu[i].x==g[j].x&&stu[i].y==g[j].y)||check(i,j,tt)){stu[i].bl=1;break;}}}}}sort(stu.begin(),stu.end(),cmp);for(int i=0;i<n;i++){if(stu[i].bl==-1)stu[i].bl=0;printf("%d",stu[i].bl);}}puts("");}return 0;}






0 0
原创粉丝点击