poj 2318 Toys(叉积判点在线段的哪一侧)

来源:互联网 发布:数据库物理模型主键 编辑:程序博客网 时间:2024/04/30 16:16

//以下为原blog搬迁过来的内容

【题目大意】:给出一个矩形的左上角的点(x1,y1)以及右下角的点(x2,y2),并给出n条线段,线段表示为(l,y1),(r,y2),用于将矩形切割成n+1块,分别标记为0到n。再给出m个点,求举行的每一块分别包含几个点。


【解题思路】:已知给出三个点a,b,c,通过叉积可以判断c在线段a,b的哪一侧,若叉积小于0,则在线段左侧,等于0,三点共线,大于0,在线段右侧。所以对于每一个点只需要找到在其右边的最左边的线段即刻。

可以先对线段的左端点进行了排序,然后求叉积,求到一个叉积<0的线段就可以了。如果写二分会快一点。 


【代码】:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip>                   using namespace std;                   #define eps 1e-8#define pi acos(-1.0)#define inf 1<<30#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long longstruct Line{    int l,r,cnt;}line[10000];int n,m,x1,yy1,x2,yy2,p,q;bool cmp(const Line &a,const Line &b){    return min(a.l,a.r)<min(b.l,b.r);}inline double det(double xx1,double yy1,double xx2,double yy2){    return xx1*yy2-xx2*yy1;}void search(int p,int q){    for (int i=0; i<=n; i++)    {        if (det(line[i].l*1.0-p*1.0,yy1*1.0-q*1.0,line[i].r*1.0-p*1.0,yy2*1.0-q*1.0)<0)        {            line[i].cnt++;            break;        }    }}int main(){    while (~scanf("%d",&n))    {        if (n==0) break;        scanf("%d%d%d%d%d",&m,&x1,&yy1,&x2,&yy2);        line[0].l=x2;        line[0].r=x2;        line[0].cnt=0;        for (int i=1; i<=n; i++)        {            scanf("%d%d",&line[i].l,&line[i].r);            line[i].cnt=0;        }        sort(line,line+n+1,cmp);        for (int i=0; i<m; i++)        {            scanf("%d%d",&p,&q);            search(p,q);        }        for (int i=0; i<=n; i++)            printf("%d: %d\n",i,line[i].cnt);        printf("\n");    }    return 0;}