[poj2318]:TOYS

来源:互联网 发布:产品防伪码制作软件 编辑:程序博客网 时间:2024/05/17 23:41

传送门
计算几何基础题——第一题
这个题需要用到的有:
1.向量
2.向量基本运算(加减法)
3.向量叉积
(https://wenku.baidu.com/view/6d53cdcd58f5f61fb73666c6.html)
(http://blog.csdn.net/hc14519/article/details/50716299)
(第一篇是ppt,必须看,讲的非常基础)
(第二篇是关于向量叉积的几何意义的讲解,虽然讲的一般,但还是可以看看)
(还有,其实叉积的几何意义可以说成这样:
(P×Q就是0,P,Q,P+Q围成的四边形的面积,带符号)
(再补充三个。。)
(http://www.matrix67.com/blog/archives/6217)
(http://www.yalewoo.com/in_triangle_test.html)
(http://blog.sina.com.cn/s/blog_4c70701801013e49.html)
4.二分法
大家学会之后再来做,相信你就会了。
关于如何用叉积判断点在直线哪一侧:

首先要知道怎么以一个点为坐标原点建立坐标系:
其实只要将所有向量减去它就好了
然后我们可以用叉积判断一个点在另一个点的顺时针还是逆时针
设向量P,Q(可抽象为坐标系上的点)
Cross(P,Q)<0,则P在Q的逆时针方向
Cross(P,Q)=0,则P,Q在同一直线上
Cross(P,Q)>0,则P在Q的顺时针方向
然后利用这个就可以判断了

然后我们就可以二分了。
代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#define ll long longusing namespace std;inline int read(){    int x=0;char ch=' ';int f=1;    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-')f=-1,ch=getchar();    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();    return x*f;}const int N=5005;const double eps=1e-12;struct Point{    double x,y;    Point(){}    Point(double _x,double _y):x(_x),y(_y){}    inline Point operator - (const Point& b) const {return Point(x-b.x,y-b.y);}};struct Line{    Point s,t;    Line(){}    Line(Point _s,Point _t):s(_s),t(_t){}}L[N];inline int dcmp(double x){    if(fabs(x)<eps)return 0;    return x>eps?1:-1;}inline double Cross(const Point& a,const Point& b){    return a.x*b.y-a.y*b.x;}inline int check(Line L,Point P){    Point P1=L.s-P,P2=L.t-P;    return dcmp(Cross(P1,P2));}int n,m,ans[N];double X1,X2,Y1,Y2;int main(){while(1){    memset(ans,0,sizeof(ans));    n=read();if(!n)break;m=read();    scanf("%lf %lf %lf %lf",&X1,&Y1,&X2,&Y2);    for(int i=1;i<=n;i++){        scanf("%lf",&L[i].t.x);L[i].t.y=Y1;        scanf("%lf",&L[i].s.x);L[i].s.y=Y2;    }    for(int i=1;i<=m;i++){        Point Ask;scanf("%lf %lf",&Ask.x,&Ask.y);        int l=0,r=n,mid;        while(l<r){            mid=(l+r+1)>>1;            if(check(L[mid],Ask)==-1)l=mid;            else r=mid-1;        }        ans[l]++;    }    for(int i=0;i<=n;i++)printf("%d: %d\n",i,ans[i]);    putchar('\n');}    return 0;}
原创粉丝点击