POJ 2318

POJ 2318

計算幾何基礎,叉積的運用,及二分求解。
題目中保證了所有玩具都是在盒子內,並且不會位於邊界上。那麼利用叉積可以判斷出玩具相對於某個邊界的方向,逆時針則在該邊界左邊,順時針則在右邊。然後二分邊界,不斷做叉積,找出該點的具體在哪兩條邊界之間即可,找出具體位置後,該區域的玩具數加一。時間複雜度O(n*lg(m))。

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define mm0(a) memset(a,0,sizeof(a));
#define debug puts("It's ok here!")
using namespace std;
const int maxn=5e3+5;
struct Point{
    int x, y;
    Point(){}
    Point(int _x, int _y):x(_x), y(_y){}
};
struct line{
    Point s, t;
    line(){}
    line(int sx,int sy,int tx,int ty){s.x=sx; s.y=sy; t.x=tx; t.y=ty;}
    line(Point _s, Point _t):s(_s), t(_t){}
};
bool crossleft(Point a,Point b,Point c){
    return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x)>0;
}
Point toy[maxn];
line board[maxn];
int n, m;
int ans[maxn];
int query(int p){
    int l=0, r=m+1;
    while(l+1<r){
        int mid=(l+r+1)>>1;
        if(crossleft(board[mid].s,toy[p],board[mid].t))
            r=mid;
        else
            l=mid;
    }
    return l;
}
int main()
{
    int x1, y1, x2, y2;
    int x, y;
    int cas=0;

    while(~scanf("%d",&m)&&m){
        if(cas++!=0) puts("");
        scanf("%d%d%d%d%d", &n, &x1, &y1, &x2, &y2);
        board[0]=line(Point(x1,y1),Point(x1,y2));
        board[m+1]=line(Point(x2,y1),Point(x2,y2));
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x1, &x2);
            board[i]=line(x1,y1,x2,y2);
        }
        for(int i=0;i<n;i++){
            scanf("%d%d",&x, &y);
            toy[i]=Point(x,y);
        }
        mm0(ans);
        for(int i=0;i<n;i++){
            int pos=query(i);
            ans[pos]++;
        }
        for(int i=0;i<m+1;i++)
            printf("%d: %d\n",i, ans[i]);
    }

    return 0;
}
發佈了54 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章