hdoj-2036題解-向量積法求任意多邊形面積
阿新 • • 發佈:2019-01-28
該題題意就是逆時針給出點的座標,求這個多邊形的面積。下面就寫一下如何用向量積法求多邊形面積。
向量積法與面積
上圖說明了如何利用向量求得三角形的面積,下面介紹一下所謂的右手法則:
如圖,2個三角形ABC,唯一的區別在於上面的三角形ABC的標識是逆時針,而下面的三角形標識是順時針。如果利用向量叉積,由於乘的是向量的絕對值,所以AB與AC在上或者在下是沒有區別的。但是如果不使用絕對值,而是寫成行列式的形式,就要考慮方向的問題了。所以簡單(不負責任)地說,所謂右手法則就是:當逆時針(右手大拇指朝向)方向排列點的時候組成的向量求的的結果是正數,反之是負數。(上面並不是標準解答,關於定義可參考wikipedia)那麼以上2個三角形轉化為行列式的時候就是下圖:
根據行列式的性質,我們也能知道兩者的值是相反的。 既然如此,我們在得到逆時針序的3點座標的情況下,利用行列式即可得到面積。例:
核心程式碼為:
int S = (0.5)*(x1*y2+x2*y3+x3*y1-x3*y2-x2*y1-x1*y3);
N邊形劃分為三角形
如上圖,任何一個N邊形都能劃分為N-3個三角形,那麼根據上面的公式,我們逆時針獲取點,就像下圖一樣,令單個三角形的面積和累加即可得到N邊形的面積。
因為右手定則,一定要逆時針。而該題輸入要求就正好是逆時針輸入。並且可以看出:A點恆不變,另兩個點是移動狀態,那麼我們就可以寫出程式碼:
以上程式碼可以得到第一個三角形ABC的面積,下面進入迴圈:int beginx, beginy, lastx, lasty, x, y; double ans; cin >> beginx >> beginy >> lastx >> lasty >> x >> y; ans = (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
n -= 3;
while (n--) {
cin >> x >> y;
ans += (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
lastx = x;
lasty = y;
}
最終即可得到解ans。
凹邊形面積
我們上面的例子都是凸邊形,對於凹邊形而言我們仍然可以得到正解,就是因為有右手定則。如上圖的凹邊形,我們仍然按照逆時針順序來求解,第一個三角形ABC,得到實際上是包括虛線在內的整體面積,那麼第二個三角形ACD,可以看到是順時針了,絕對值是有虛線的ACD面積,那麼因為是順時針,用行列式求出的值是負數。兩個行列式值相加,正好是大三角形(包括虛線)ABC面積減去小三角形ACD的面積。得到的仍然是凹邊形的面積。
C++程式碼
#include<iostream>
using namespace std;
int main() {
int n;
while (cin >> n) {
if (n == 0) break;
int beginx, beginy, lastx, lasty, x, y;
double ans;
cin >> beginx >> beginy >> lastx >> lasty >> x >> y;
ans = (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
lastx = x;
lasty = y;
n -= 3;
while (n--) {
cin >> x >> y;
ans += (double)(0.5)*(beginx*lasty + lastx*y + x*beginy - x*lasty - lastx*beginy - beginx*y);
lastx = x;
lasty = y;
}
printf("%.1lf\n", ans);
}
system("pause");
return 0;
}