POJ 2318 TOYS(叉积+二分)

题目链接: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 5005

const 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:判断一个点是否在三角形内部可以用面积法。


你可能感兴趣的:(POJ 2318 TOYS(叉积+二分))