程序员人生 网站导航

ZOJ 3871 Convex Hull(计数)

栏目:php教程时间:2015-05-11 08:53:36

1个n边形的面积,可以3角剖分成n 个每一个边和原点构成的3角形的有向面积

这样每条边等于1个有向面积,那末问题转化成只要求每条边能作为几个凸包的边

那末枚举1点O,这样对任意1点X会有1条OX的边,而这条边构成凸包的数量,明显就是只能在和他夹角180度之内的边之内找,也就是有多少个点,就是2^num - 1(由于最少要有1个点)

因而进行极角排序,双指针扫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(⑴.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 ", ans); } return 0; }


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐