[poj2318]:TOYS

传送门
计算几何基础题——第一题
这个题需要用到的有:
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 long
using 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值