POJ2318计算几何

http://acm.pku.edu.cn/JudgeOnline/problem?id=2318

题意:给你一块面积,给你n条线把这个面积分成n+1块,然后给m个点最后输出从第0块到第n块各有几个点;

关键:知道计算几何中一个基本定理,就是向量叉乘(向量叉积),给你一个点g(x,y)一条线(两个端点a(x,y),b(x,y)),判断点是在线的左边还是右边。向量(g-b)*向量(a-b)<0的话,点就在线的左边,>0就在右面。(判断的依据就是两个向量(g-b)*(a-b)<0的话,向量(g-b)就在向量(a-b)的逆时针方向,>0的话,向量(g-b)就在向量(a-b)的顺时针方向,都是以第二个向量为依据)

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct point
{
    int x,y;
};
point a[5010],b[5010];//a是线上面的点,b是下面的点
int c[5010];//分出来的点的计数的数组
int det(point a,point b,point g)//(g-b)*(a-b)
{
    return (g.x-b.x)*(a.y-b.y)-(a.x-b.x)*(g.y-b.y);
    //x1*y2-x2*y1
}
int main()
{
    int n,m;
    point g,g1,g2;
    int minn,maxn;
    while(scanf("%d",&n)!=EOF&&n)
    {
        scanf("%d",&m);
        scanf("%d%d%d%d",&g1.x,&g1.y,&g2.x,&g2.y);
        //面积边界
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&a[i].x,&b[i].x);
        }
        a[n+1].x=g2.x;
        b[n+1].x=g2.x;
        a[0].x=g1.x;
        b[0].x=g1.x;
        for(int i=0; i<=n+1; i++)
        {
            a[i].y=g1.y;
            b[i].y=g2.y;
            c[i]=0;
        }
        n++;
        int mid,t;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&g.x,&g.y);
            minn=0;
            maxn=n;
            while(1)
            {
                mid=(minn+maxn)>>1;
                t=det(a[mid],b[mid],g);
                if(t<0)maxn=mid;
                else minn=mid;
                if(mid+1==maxn)break;
            }
            c[minn]++;
        }//二分查找,每次从中间的一根线判断
        for(int i=0; i<n; i++)//从第0块到原第n块
        {
            printf("%d: %d\n",i,c[i]);
        }
        printf("\n");
    }
    return 0;
}

 

 

posted @ 2013-08-07 15:44  拼搏今朝 努力奋进  阅读(222)  评论(0)    收藏  举报