题目大意:给n个二维坐标点,保证任意三点不共线,问能构成的不同凸四边形的个数。
解题思路:
- 思路1:找对角线段,相交则为凸四边形,否则为凹多边形;
- 思路2:利用面积,如果为凹四边形其中必然存在一个由三点构成的三角形等于其他三个由三点构成的三角形的和,否则为凸多边形。给的是坐标,可以利用叉积公式计算三角形的面积。如果用海伦公式计算的话可能会精度问题导致WA,因为其中做了许多开根号。
- 思路3:未完成,先把选进来的四个点按顺时针排序,仍然是利用叉积的结果判断两个向量的相对位置,如果大于0表示后面那个向量在前面向量的顺时针方向,小于0在逆时针方向,等于0两向量共线。其中需要找到一个多边形内部的一点,然后扫描一下。接着利用反余弦函数和向量点乘计算出夹角,然后判断内角和是否为360,其中反余弦函数范围在0~PI内。
Code:
#include <iostream>
#include <math.h>
#include <algorithm>
#include <string.h>
#include <string>
using namespace std;
const int maxn = (int)3e1+5;
const double esp = 1e-6;
struct point {
int x, y;
};
point tab[maxn];
/* inline double calc_len (point& A, point& B) { return sqrt(1.0*(A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); } inline double calc_area(double a, double b, double c) { double p = (a + b + c) / 2; return sqrt(1.0 * p * (p - a) * (p - b) * (p - c)); } */
inline double calc_area(point& A, point& B, point& C) {
return fabs((B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x)) / 2.0;
}
double l1, l2, l3, l4, l5, l6;
double s1, s2, s3, s4;
int main() {
int T, n;
cin >> T;
for (int i = 1; i <= T; i++) {
cin >> n;
for (int j = 0; j < n; j++) { //io
cin >> tab[j].x >> tab[j].y;
}
int cnt = 0;
for (int j = 0; j < n; j++) {
for (int z = j + 1; z < n; z++) {
for (int k = z + 1; k < n; k++) {
for (int p = k + 1; p < n; p++) {
/* l1 = calc_len(tab[j], tab[z]); l2 = calc_len(tab[j], tab[p]); l3 = calc_len(tab[z], tab[k]); l4 = calc_len(tab[j], tab[k]); l5 = calc_len(tab[k], tab[p]); l6 = calc_len(tab[p], tab[z]); s1 = calc_area(l1, l2, l6); s2 = calc_area(l1, l4, l3); s3 = calc_area(l2, l4, l5); s4 = calc_area(l3, l5, l6); */
s1 = calc_area(tab[j], tab[z], tab[k]);
s2 = calc_area(tab[j], tab[z], tab[p]);
s3 = calc_area(tab[j], tab[k], tab[p]);
s4 = calc_area(tab[p], tab[z], tab[k]);
if (fabs(s1 - s2 - s3 - s4) < esp || fabs(s2 - s1 - s3 - s4) < esp ||
fabs(s3 - s2 - s1 - s4) < esp || fabs(s4 - s2 - s3 - s1) < esp) {
continue;
}
cnt++;
}
}
}
}
cout << "Case " << i << ": " << cnt << endl;
}
return 0;
}