POJ 2318 TOYS(叉积+二分)

来源:互联网 发布:网络安全教育感想 编辑:程序博客网 时间:2024/05/21 22:37

题目链接:Click here~~

题意:

有一个矩形的盒子,中间插了n个挡板,将盒子分成n+1个区域,然后给m个点,问最后每个区域落下多少个点。(点不会落到挡板上)

解题思路:

把矩形的右边看成第n+1个挡板。

稍加分析,得到这个特点:若点 k 在挡板 i 的左边,那么 k 也一定在挡板 j 的左边(i < j <= n+1)。

则对于每一个点k,只要找到最小的挡板 i ,满足点 k 在挡板 i 的左边,则点 k 就在区域 i 中。

如此,即可转换成二分的模型来求解。

#include <math.h>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define N 5005const double eps = 1e-6;struct Point{    int x,y;    Point(){}    Point(int x,int y):x(x),y(y){}}p,pp1,pp2,pp3,pp4;struct Rec{    Point p1,p2,p3,p4;    Rec(){}    Rec(Point p1,Point p2,Point p3,Point p4):p1(p1),p2(p2),p3(p3),p4(p4){}}R[N];int ans[N];int sgn(double x){    return fabs(x)<eps ? 0 : (x > eps ? 1 : -1);}double Cross(const Point& p1,const Point& p2,const Point& p3,const Point& p4){    return (p2.x-p1.x)*(p4.y-p3.y) - (p2.y-p1.y)*(p4.x-p3.x);}double Area(const Point& p1,const Point& p2,const Point& p3){    return fabs(Cross(p1,p2,p1,p3));}bool InTri(const Point& p,const Point& p1,const Point& p2,const Point& p3){    return Area(p,p1,p2) + Area(p,p2,p3) + Area(p,p3,p1) == Area(p1,p2,p3);}bool InRec(const Point& p,const Point& p1,const Point& p2,const Point& p3,const Point& p4){    return InTri(p,p1,p2,p3) || InTri(p,p1,p3,p4);}int Search(Point p,int l,int r){    while(l < r)    {        int mid = (l+r)/2;        if(Cross(p,R[mid].p4,p,R[mid].p3) > 0)            l = mid+1;        else            r = mid;    }    return r;}int main(){    int n,m,x1,x2,minx,maxy,maxx,miny;    bool first = true;    while(scanf("%d",&n),n)    {        if(!first)            puts("");        else            first = false;        memset(ans,0,sizeof(ans));        scanf("%d%d%d%d%d",&m,&minx,&maxy,&maxx,&miny);        pp1 = Point(minx,maxy);        pp2 = Point(minx,miny);        for(int i=0;i<n;i++)        {            scanf("%d%d",&x1,&x2);            pp3 = Point(x2,miny);            pp4 = Point(x1,maxy);            R[i] = Rec(pp1,pp2,pp3,pp4);            pp1 = pp4 , pp2 = pp3;        }        R[n] = Rec(pp1,pp2,Point(maxx,miny),Point(maxx,maxy));        for(int i=0;i<m;i++)        {            scanf("%d%d",&p.x,&p.y);            ans[Search(p,0,n)]++;        }        for(int i=0;i<=n;i++)            printf("%d: %d\n",i,ans[i]);    }return 0;}

Ps:判断一个点是否在三角形内部可以用面积法。


原创粉丝点击