标签:
一个n边形的面积,可以三角剖分成n 个每个边和原点构成的三角形的有向面积
这样每条边等于一个有向面积,那么问题转化成只要求每条边能作为几个凸包的边
那么枚举一点O,这样对于任意一点X会有一条OX的边,而这条边构成凸包的数量,显然就是只能在和他夹角180度以内的边以内找,也就是有多少个点,就是2^num - 1(因为至少要有一个点)
于是进行极角排序,双指针扫一遍就能得到所有答案
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; const int MOD = 998244353; const int N = 1005; const double pi = acos(-1.0); struct Point { int x, y; double ang; void read() { scanf("%d%d", &x, &y); } }; bool cmp(Point a, Point b) { return a.ang < b.ang; } int t, n; Point p[N], tmp[N * 2]; int pow2[N]; int area(Point a, Point b) { return (((ll)a.x * b.y % MOD - (ll)a.y * b.x % MOD ) % MOD + MOD) % MOD;; } int main() { scanf("%d", &t); pow2[0] = 1; for (int i = 1; i < N; i++) pow2[i] = pow2[i - 1] * 2 % MOD; while (t--) { int ans = 0; scanf("%d", &n); for (int i = 0; i < n; i++) p[i].read(); for (int i = 0; i < n; i++) { int tn = 0; for (int j = 0; j < n; j++) { if (i == j) continue; tmp[tn] = p[j]; tmp[tn++].ang = atan2(p[j].y - p[i].y, p[j].x - p[i].x); } for (int j = 0; j < tn; j++) { tmp[j + tn] = tmp[j]; tmp[j + tn].ang += pi * 2; } sort(tmp, tmp + tn * 2, cmp); int r = 0; for (int l = 0; l < tn; l++) { while (tmp[r + 1].ang - tmp[l].ang < pi) r++; ans = (ans + (ll)area(p[i], tmp[l]) * ((pow2[r - l] - 1 + MOD) % MOD) % MOD) % MOD; } } printf("%d\n", ans); } return 0; }
标签:
原文地址:http://blog.csdn.net/accelerator_/article/details/45365039