Graham算法模板 F 题Saint John Festival 20152016-acmicpc-southwestern-europe-regional-

来源:互联网 发布:数据挖掘技术 客户微盘 编辑:程序博客网 时间:2024/05/21 09:24

题目就是要求解有多少个点可以被至少一个三角形围住,这个点可以在三角形的边上

题解:

每一个点肯定会在最大的凸包里面,所以我们求解一个凸包,然后二分点,寻找这样的三角形即可


#include<math.h>#include<stdio.h>#include<stdlib.h>#include<iostream>#include<algorithm>using namespace std;#define MAXN 10005const double eps=1e-8;struct Point{    double x,y;    Point(){}    Point(double _X, double _Y){        x = _X; y = _Y;    }};Point P[MAXN];int Stack[MAXN],top;///下标从0开始计数到topdouble Cross(Point p1,Point p2,Point p3){    return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);}double Dis(Point A, Point B){    return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y));}Point operator - (Point A,Point B){    return Point(A.x-B.x, A.y-B.y);}Point operator + (Point A, Point B){    return Point(A.x+B.x, A.y+B.y);}Point operator * (Point A, double p){    return Point(A.x*p, A.y*p);}bool operator == (Point A, Point B){    return (A.x-B.x) == 0 && (A.y-B.y) == 0;}int sgn(double x){    if(fabs(x)<eps)        return 0;    if(x<0)        return -1;    return 1;}bool cmp(Point A, Point B)///按极角升序排序,若角度相等距离小的在前面{    double temp = sgn(Cross(P[0],A,B));    if(temp > 0) return true;    else if(temp==0&&(sgn(Dis(P[0], A) - Dis(P[0], B)))<=0) return true;    else return false;}void Graham(int n){    double xx=P[0].x,yy=P[0].y;    int id=0;//找到y坐标最小的点,若有多个选择x坐标最小的记录下标    for(int i=1;i<n;i++){        if(P[i].y<yy || (P[i].y==yy&&P[i].x<xx)){            xx = P[i].x;            yy = P[i].y;            id = i;        }    }    Point T=P[0];    P[0]=P[id];    P[id]=T;    sort(P+1,P+n,cmp);    if(n==1){        top=1;        Stack[0]=0;        return;    }    if(n==2){        top=2;        Stack[0]=0;        Stack[1]=1;        return ;    }    Stack[0]=0;    Stack[1]=1;    top=2;    for(int i=2;i<n;i++)    {        while(top>1&&sgn(Cross(P[Stack[top-2]],P[Stack[top-1]],P[i]))<=0)            top--;        Stack[top++]=i;    }}bool judge(Point temp){    int left,right,mid;    double t1,t2,t3;    left=1,right=top-2;    while(left<=right)    {        mid=(left+right)/2;        Point a=P[Stack[0]],b=P[Stack[mid]],c=P[Stack[mid+1]];        t1=Cross(a,b,temp);        t2=Cross(a,c,temp);        if(t1>=0&&t2<=0){            t3=Cross(b,c,temp);            if(t3>=0)                return true;            return false;        }        if(t1<0)            right=mid-1;        else            left=mid+1;    }    return false;}int main(){    int n,s;    //freopen("in.txt","r",stdin);    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)            scanf("%lf%lf",&P[i].x,&P[i].y);        Graham(n);        scanf("%d",&s);        int ans=0;        Point num;        while(s--)        {            scanf("%lf%lf",&num.x,&num.y);            if(judge(num))                ans++;        }        printf("%d\n",ans);    }    return 0;}


阅读全文
0 0
原创粉丝点击