POJ 2318 TOYS (叉積)
阿新 • • 發佈:2018-12-15
題意:給你一個矩形,再給你一些邊,這些邊把矩形分成了一些區域,然後再給你一些點,問各個區域的點的個數。
題解:這道題,需要用到向量的叉積這個知識點。
先普及一下關於向量的知識
向量:在數學中既有大小又有方向的量成為向量(或向量)。
向量加減法:向量P(x1,y1) ,向量(x2,y2)
向量P + 向量Q = (x1+x2,y1+y2);
向量P - 向量Q = (x1 - x2,y1 - y2);
向量點積 :
向量P·向量Q = x1 * x2 + y1 * y2
向量叉積 :
向量P × 向量Q = x1*y2 - x2*y1
叉積性質:判斷兩個向量之間的順逆關係 以下設 向量P×向量Q 的結果為 ans
若ans > 0 則向量P在Q的順時針方向
若ans < 0 則向量P在Q的逆時針方向
若ans == 0 則向量 P 與 向量Q 共線,但是可能同向也可能反向。
所以這道題,我們可以用叉積的性質來解決,把每一條分割線看作一個向量,選擇一條邊,然後給這些向量按x排序,然後讓給出點的起點和分割線的起點相同,給出點的終點為該點,然後利用叉積來判斷即可。
具體看程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 5005; struct point{ double x; double y; }; struct v{ // 向量 point start; // 起始點的座標 point end; // 終點的座標 }lim[maxn]; int book[maxn]; double cha(v) double crossProduct(v* v1,v* v2){ //計算兩個 向量的 叉積 v vt1,vt2; // 定義兩個向量 double result = 0; // 存叉積 vt1.start.x = 0; // 把向量 v1 轉成起點從(0,0)開始 vt1.start.y = 0; vt1.end.x = v1->end.x - v1->start.x; vt1.end.y = v1->end.y - v1->start.y; vt2.start.x = 0; // 把向量 v2 轉成起點從(0,0)開始 vt2.start.y = 0; vt2.end.x = v2->end.x - v2->start.x; vt2.end.y = v2->end.y - v2->start.y; result = vt1.end.x * vt2.end.y - vt2.end.x * vt1.end.y; // 計算叉積 return result; } bool cmp(v x,v y){ // 對向量按照x排序 return x.start.x < y.start.x; } int main(){ int n,m,x1,x2,y1,y2; while(~scanf("%d",&n)){ memset(book,0,sizeof(book)); if(n == 0 ) break; scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); for(int i = 0 ; i < n ; i ++){ double x,y; scanf("%lf%lf",&x,&y); lim[i].start.x = x; // 建立向量 lim[i].start.y = y1; lim[i].end.x = y; lim[i].end.y = y2; } lim[n].start.x = x2; // 加上最後一個區域 lim[n].start.y = y1; lim[n].end.x = x2; lim[n].end.y = 0; sort(lim,lim+n+1,cmp); for(int i = 0 ; i < m; i ++){ double x,y; scanf("%lf%lf",&x,&y); for(int j = 0 ; j <= n ; j ++){ v temp; temp.start = lim[j].start; temp.end.x = x; temp.end.y = y; double ans = crossProduct(&temp,&lim[j]); if(ans >= 0){ //根據叉積定義來統計 book[j] ++; break; } } } for(int i = 0 ; i <= n ; i ++){ printf("%d: %d\n",i,book[i]); } printf("\n"); } return 0; }