點乘php
一個向量在另外一個向量上的投影長度,標量,用於判斷角度html
叉乘ios
垂直兩向量的平面,右手定則,矢量,用於判斷方向spa
參考博客:點擊進入
code
(1)快速排斥試驗htm
設以線段 P1P2 爲對角線的矩形爲R, 設以線段 Q1Q2 爲對角線的矩形爲T,若是R和T不相交,顯然兩線段不會相交。blog
(2)跨立試驗
ci若是兩線段相交,則兩線段必然相互跨立對方。若P1P2跨立Q1Q2 ,則矢量 ( P1 - Q1 ) 和( P2 - Q1 )位於矢量( Q2 - Q1 ) 的兩側,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改寫成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。當 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 時,說明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共線,可是由於已經經過快速排斥試驗,因此 P1 必定在線段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 說明 P2 必定在線段 Q1Q2上。因此判斷P1P2跨立Q1Q2的依據是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判斷Q1Q2跨立P1P2的依據是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。get
例題:51nod1264博客
1 #include<iostream> 2 using namespace std; 3 4 struct Point 5 { 6 double x, y; 7 } dot[4]; 8 9 double cross(Point a, Point b, Point c) 10 { 11 double nx1, ny1, nx2, ny2; 12 nx1 = b.x - a.x; 13 ny1 = b.y - a.y; 14 nx2 = c.x - b.x; 15 ny2 = c.y - b.y; 16 return nx1 * ny2 - ny1 * nx2; 17 } 18 19 int main() 20 { 21 int t; 22 cin >> t; 23 while(t--) 24 { 25 for(int i = 0; i < 4; i++) 26 cin >> dot[i].x >> dot[i].y; 27 double s1, s2, s3, s4; 28 //這裏的三點順序須要注意,可由叉乘相關性質推導出 29 s1 = cross(dot[0], dot[2], dot[3]); 30 s2 = cross(dot[3], dot[2], dot[1]); 31 s3 = cross(dot[2], dot[0], dot[1]); 32 s4 = cross(dot[1], dot[0], dot[3]); 33 if(s1 * s2 >= 0 && s3 * s4 >= 0) 34 cout << "YES" << endl; 35 else 36 cout << "NO" << endl; 37 } 38 return 0; 39 }
關於上面的順序問題,畫個圖加深一下理解
例題:hdu1086
1 #include<iostream> 2 using namespace std; 3 4 struct Point 5 { 6 double x, y; 7 } dot[220]; 8 9 struct Seg 10 { 11 Point fir, sec; 12 } Seg[110]; 13 14 double cross(Point a, Point b, Point c) 15 { 16 double nx1, ny1, nx2, ny2; 17 nx1 = b.x - a.x; 18 ny1 = b.y - a.y; 19 nx2 = c.x - b.x; 20 ny2 = c.y - b.y; 21 return nx1 * ny2 - ny1 * nx2; 22 } 23 24 int is_cross(Point a, Point b, Point c, Point d) 25 { 26 double s1, s2, s3, s4; 27 s1 = cross(a, c, d); 28 s2 = cross(d, c, b); 29 s3 = cross(c, a, b); 30 s4 = cross(b, a, d); 31 if(s1 * s2 >= 0 && s3 * s4 >= 0) 32 return 1; 33 return 0; 34 } 35 int main() 36 { 37 int n; 38 while(cin >> n && n) 39 { 40 int ans = 0; 41 for(int i = 0; i < n; i++) 42 { 43 cin >> Seg[i].fir.x >> Seg[i].fir.y >> Seg[i].sec.x >> Seg[i].sec.y; 44 } 45 for(int i = 0; i < n; i++) 46 { 47 for(int j = i + 1; j < n; j++) 48 { 49 if(is_cross(Seg[i].fir, Seg[i].sec, Seg[j].fir, Seg[j].sec)) 50 ans++; 51 } 52 } 53 cout << ans << endl; 54 } 55 return 0; 56 }
體會:
計算幾何題須要對幾何知識有必定的熟悉,有時一行公式代碼可能要推導一下子時間,因此我的感受這類題模板和公式總結很重要,慢慢積累吧~