「HDU3629」Convex-计算几何

Description

链接

Solution

考虑平面相交线段对数等于平面凸四边形数(相交线段相当于对角线)。

平面凸四边形个数转化为总数减去凹四边形数。

凹四边形数相当于一个三角形中包含了一个点。

枚举被包含的点,计算包含它的三角形比较麻烦,统计不包含它的三角形。

极角排序后,若两个向量 i , j i,j i,j之间的夹角小于 π \pi π,那么 i + 1 i+1 i+1 j j j的向量任意选出两个与 i i i组合一定能组成不包含当前点的三角形,two-pointers统计即可。

#include 
using namespace std;

typedef long long lint;

const int maxn = 705;
const double pi = acos(-1);

int n;
int x[maxn], y[maxn], tot;
lint ans;

struct point
{
	int x, y;
	double angle;

	bool operator < (const point &a) const {
		return angle < a.angle;
	}
	
} p[maxn * 2];

inline int gi()
{
	char c = getchar(); bool f = 1;
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') c = getchar(), f = 0;
	int sum = 0;
	while ('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return f ? sum : -sum;
}

lint solve(int k)
{
	lint res = (lint)(n - 1) * (n - 2) * (n - 3) / 6;
	tot = 0;
	for (int i = 1; i <= n; ++i)
		if (i != k) {
			p[++tot] = (point) {x[i] - x[k], y[i] - y[k]}; p[tot].angle = atan2(p[tot].y, p[tot].x);
			p[++tot] = (point) {x[i] - x[k], y[i] - y[k]}; p[tot].angle = p[tot - 1].angle + pi * 2;
		}
	sort(p + 1, p + tot + 1);
	for (int i = 1, j = 0; i < n; ++i) {
		while (p[j + 1].angle - p[i].angle <= pi) ++j;
		if (j - i >= 2) res -= (j - i) * (j - i - 1) / 2;
	}
	return res;
}

int main()
{
	freopen("convex.in", "r", stdin);
	freopen("convex.out", "w", stdout);

	int T = gi();
	while (T--) {
		n = gi();
		for (int i = 1; i <= n; ++i) x[i] = gi(), y[i] = gi();
		ans = (lint)n * (n - 1) * (n - 2) * (n - 3) / 24;
		for (int i = 1; i <= n; ++i) ans -= solve(i);
		printf("%lld\n", ans);
	}
	
	return 0;
}

你可能感兴趣的:(文章类型——题解,计算几何——极角排序)