POJ2318 (二分加叉積使用)
阿新 • • 發佈:2018-12-21
題目大意:給你一個矩形和一些線段,給的這些線段將矩形分割為從左到右的若干個部分(不會相交,點不會再線上,題意給出了),之後給出一些玩具的座標,求分割的若干部分每個部分的玩具數量。
題解:這是一個計算幾何的水題,考一些基礎問題,我們注意,題目上給線段的順序是從左到右給出的,我們可以考慮的是每一個點(玩具)是在這條線的左邊還是右邊,(一定會存在一個分界使它的左邊的線段都在玩具的右邊,它右邊的玩具都在玩具的左邊)
於是我們能想出來這種情況下我們要用二分來寫:
然後我們根據叉積判斷點和線段的關係(我們可以將點減去線段的起點和原線段組成兩個同七點的向量,然後我們根據叉積的性質:
若P×Q > 0 , 則P在Q的順時針方向;
若P×Q < 0 , 則P在Q的逆時針方向;
若P×Q = 0 , P與Q共線,可能是同向也可能是反向
因為題目上說了,玩具保證不會落在分界線上,所以不用考慮)
特別注意:本題的陣列有點兒多吧,注意初始化每一個數組。
AC程式碼如下:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int mx = 666666; int u[mx] , v[mx] , ans[mx]; int chachen(int x1 , int y1 , int x2 , int y2) { return x1 * y2 - x2 * y1; } int main() { int n , m , x1 , y1 , x2 , y2 , flag = 0 ; while(scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2) == 6) { if(flag) puts(""); flag = 1; memset(ans,0,sizeof(ans)); for(int i = 0 ; i < n ; i ++) { scanf("%d %d",&u[i],&v[i]); } int x , y ; for(int i = 1 ; i <= m ; i ++) { cin>>x>>y; int high = n , mid , low = 0 ; while(low < high) { mid = (low + high) / 2 ; if(chachen(u[mid] - x , y1 - y , v[mid] - x , y2 - y) <= 0) high = mid; else low = mid + 1 ; } ans[low]++; } for(int i = 0 ; i <= n ; i ++) { printf("%d: %d\n",i,ans[i]); } } return 0 ; }
有的可能就是sort掃一遍然後輸出就能過,可能使後臺資料太水吧,那個我看要900多Ms,但是用二分的話差不多500Ms執行完