X-man

导航

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

题意:

  在二维平面上,给定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;
}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:构造凸包之后去重点

#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:

#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

 

posted on 2014-08-15 16:54  雨钝风轻  阅读(443)  评论(0编辑  收藏  举报