ZOJ 3871 Convex Hull(計數)
來源:程序員人生 發布時間:2015-05-11 08:53:36 閱讀次數:4488次
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;
}
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈