ACM練級日誌:POJ 2318 叉積的簡單應用

最近開始學習計(keng)算(die)幾何,第一道入門題就是這道了。

本題最核心的問題,就是如何判斷一個點在直線(線段)的什麼位置。這一點叉積可以很容易地做到。

設直線(線段)的向量爲S->E, 詢問點爲P, 那麼我們只需要計算一下 S->P x S->E, 如果大於0,說明S->P 順時針旋轉會達到S->E, 等於0說明就在直線上,小於0說明它需要逆時針旋轉才能達到S->E。 

在這道題裏,如果我們始終選擇S是上面的點,E是下面的點的話,那麼S->P如果順時針旋轉能達到S->E,說明P在這條線段左邊,就滿足要求了。用叉積判斷的時候,大於0小於0跟你所選的向量起終點以及誰x誰都有關係,最後判出順時針逆時針也需要自己想想是在直線的哪邊……


最後是代碼,第一次寫,可能還比較醜陋……


#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
 
typedef long long LL;
     
struct ptype
{
    LL x,y;
    ptype(){x=0; y=0;};
     
    ptype(LL _x, LL _y)
    {
        x=_x;
        y=_y;
    }
    ptype operator + (ptype p)
    {
        return ptype(x+p.x , y+p.y);
    }
    ptype operator - (ptype p)
    {
        return ptype(x-p.x, y-p.y);
    }
    LL cross(ptype p)
    {
        return x * p.y - y * p.x;
    }
};
 
struct segtype
{
    ptype s,e;
};
 
int n,m;
LL box_x0, box_y0, box_x1, box_y1;
segtype seg[5010];
int ans[5010];
 
void init()
{
    memset(seg, 0 , sizeof(seg));
    memset(ans, 0, sizeof(ans));
    return;
}
 
int main()
{
    while(true)
    {
        scanf("%d", &n);
        if(n==0)
            break;
        scanf("%d %I64d %I64d %I64d %I64d", &m, &box_x0, &box_y0, &box_x1, &box_y1);
         
        init();
         
        int i;
        for(i=1;i<=n;i++)
        {
            LL tx1, tx2;
            scanf("%I64d %I64d", &tx1, &tx2);
            ptype s(tx1, box_y0);
            ptype e(tx2, box_y1);
             
            seg[i].s = s;
            seg[i].e = e;
             
        }
         
        for(i=1;i<=m;i++)
        {
            LL tx1, tx2;
            scanf("%I64d %I64d", &tx1, &tx2);
            ptype now(tx1, tx2);
             
            int low=1, high=n+1;
            while(low < high)
            {
                int mid = (high+low)/2;
                ptype seg_s = seg[mid].s;
                ptype seg_e = seg[mid].e;
                 
                ptype line(seg_e - seg_s);
                ptype now_vec(now - seg_s);
                 
                if( now_vec.cross(line) > 0)
                    high = mid;
                else
                    low = mid+1;
            }
             
            ans[high]++;
             
        }
         
        for(i=1;i<=n+1;i++)
        {
            printf("%d: %d\n", i-1, ans[i]);
        }
        printf("\n");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章