天天看點

[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=;char ch=' ';int f=;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')f=-,ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<)+(x<<)+(ch^),ch=getchar();
    return x*f;
}

const int N=;
const double eps=;
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 ;
    return x>eps?:-;
}
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(){
    memset(ans,,sizeof(ans));
    n=read();if(!n)break;m=read();
    scanf("%lf %lf %lf %lf",&X1,&Y1,&X2,&Y2);
    for(int i=;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=;i<=m;i++){
        Point Ask;scanf("%lf %lf",&Ask.x,&Ask.y);
        int l=,r=n,mid;
        while(l<r){
            mid=(l+r+)>>;
            if(check(L[mid],Ask)==-)l=mid;
            else r=mid-;
        }
        ans[l]++;
    }
    for(int i=;i<=n;i++)printf("%d: %d\n",i,ans[i]);
    putchar('\n');
}
    return ;
}