题目大意:
二维坐标系上 N ( ≤ 500 ) N(\le 500) N(≤500)个红点, M ( ≤ 500 ) M(\le 500) M(≤500)个蓝点,任意三点都不共线,求有多少个红点构成的三角形其中不包含蓝点
解题思路:
- 先设一个最左下角点 O O O,设 n u m [ i ] ] [ j ] num[i]][j] num[i]][j]为 △ O i j \triangle Oij △Oij( i , j 均 为 红 点 i,j均为红点 i,j均为红点)内有多少个蓝色点,如果 O i Oi Oi在 O j Oj Oj的逆时针方向则 n u m [ i ] [ j ] num[i][j] num[i][j]为负
- 最后只要枚举红点,看有多少个 n u m [ i ] [ j ] + n u m [ j ] [ k ] + n u m [ k ] [ i ] = 0 num[i][j]+num[j][k]+num[k][i]=0 num[i][j]+num[j][k]+num[k][i]=0即可
- 其实原理就是类似利用叉积计算凸多边形面积
AC代码:
#include <bits/stdc++.h>
#define ft first
#define sd second
#define pb push_back
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) //不能跟puts混用
#define seteps(N) fixed << setprecision(N)
#define endl "\n"
const int maxn = 5e2 + 10;
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
const ll mod = 1e9 + 7;
const ll inf = 1e9 + 10;
struct Point {
ll x, y;
Point operator - (Point p) {return {x - p.x, y - p.y};}
ll operator ^ (Point p) {return x * p.y - y * p.x;}
} p1[maxn], p2[maxn], o;
int n, m, num[maxn][maxn];
int sgn(ll x) {
if (x < 0) return -1;
else if (x > 0) return 1;
else return 0;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%lld%lld", &p1[i].x, &p1[i].y);
for (int i = 1; i <= m; i++) scanf("%lld%lld", &p2[i].x, &p2[i].y);
o = {-inf, -inf};
int s1, s2;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
for (int k = 1; k <= m; k++) {
s1 = sgn((p2[k] - o) ^ (p1[i] - o));
Point test1 = p2[k] - o, test2 = p1[i] - o, test3 = p1[j] - o;
s2 = sgn((p2[k] - o) ^ (p1[j] - o));
if (s1 * s2 > 0) continue;
s1 = sgn((p2[k] - p1[i]) ^ (p1[j] - p1[i]));
s2 = sgn((p2[k] - p1[i]) ^ (o - p1[i]));
if (s1 * s2 > 0) continue;
num[i][j]++;
}
s1 = sgn((p1[i] - o) ^ (p1[j] - o));
num[i][j] *= s1;
num[j][i] = -num[i][j];
}
}
// for (int i = 1; i <= n; i++)
// for (int j = 1; j <= n; j++)
// cout << num[i][j] << " \n"[j == n];
ll ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
for (int k = j + 1; k <= n; k++) {
if (num[i][j] + num[j][k] + num[k][i] == 0)
ans++;
}
}
}
printf("%lld\n", ans);
return 0;
}