最近開始學習計(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;
}