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

题意:

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

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

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

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

 

思路:

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

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

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

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

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

 

#易错点:

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

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

 

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

hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)
#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;

}p[MAX],Ini[MAX],res[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);

    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];

    }

    int t=top+1;

    for(i=n-2;i>=0;i--)

    {

        while(top>=t&&cross(res[top-2],res[top-1],p[i])<0)

            top--;

        res[top++]=p[i];

    }

    /*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==Ini[i].v)tmp++;

            else break;

        }

        point po;

        for(i=0,j=0;i<tmp;)

        {

            po=Ini[i];

            if(i<tmp-1&&Ini[i+1].x==Ini[i].x&&Ini[i+1].y==Ini[i].y)

            {

                while(i<tmp-1&&Ini[i+1].x==Ini[i].x&&Ini[i+1].y==Ini[i].y)

                    i++;

            }

            else

            {

                p[j++]=po;

            }

            i++;

        }

        printf("Case #%d: ",++__case);



        int m=Graham(p,j);



        memset(ans,0,sizeof(ans));

        for(i=0;i<m;i++)

        {

            //printf("%d %d %d",res[i].x,res[i].y,res[i].v);

            if(res[i].v>0)

            {

                ans[res[i].i]=1;

            }

        }

        for(i=0;i<n;i++)

            printf("%d",ans[i]);

        printf("\n");

    }

    return 0;

}
View Code

WA:构造凸包之后去重点

hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)
#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];

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;

    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;

        }

        int m=Graham(Ini,tmp);

        memset(ans,0,sizeof(ans));

        printf("Case #%d: ",++__case);

        point po;

        for(i=0; i<m; i++)

        {

            po=res[i];

            //printf("#%d %d %d\n",res[i].x,res[i].y,res[i].i);

            if(i<m-1&&res[i+1].x==po.x&&res[i+1].y==po.y)

            {

                while(i<m-1&&res[i+1].x==po.x&&res[i+1].y==po.y)

                    i++;

            }

            else

                ans[po.i]=1;

        }

        for(i=0; i<n; i++)

            printf("%d",ans[i]);

        printf("\n");

    }

    return 0;

}
View Code

数据:

9

0 0 1

0 0 1

0 10 1

0 10 1

10 0 1

10 0 1

10 10 1

10 10 1

5 5 1

 

构造凸包之前去掉重点,保留相同点中的一个。

AC:

hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)
#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

 

你可能感兴趣的:(oom)