LOJ 2882「JOI Spring Camp 2014 Day4」两个人的星座 (极角排序)
题目链接:https://loj.ac/p/2882
极角排序:使用 \(atan2(y,x)\)函数,返回点与原点的连线与 \(x\) 轴的夹角,范围是 \([-180,180]\),可以加上 \(pi\),使得范围为 \([0,360]\)
题解:
若两个三角形不相交,则一定存在两条切线,使得两个三角形分别在切线的两端,
于是枚举每个点,按极角序枚举切线,统计切线两侧不同颜色点的数量,计算即可,具体实现参考代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3010;
const double eps = 1e-8;
const double pi = acos(-1.0);
int n;
int c[maxn];
ll sum[3][maxn];
ll ans = 0;
struct Point{
int x, y, c;
double k;
bool operator < (const Point &b) const {
return k < b.k;
}
}a[maxn], b[maxn];
Point operator + (Point a, Point b){ return (Point){a.x + b.x, a.y + b.y}; }
Point operator - (Point a, Point b){ return (Point){a.x - b.x, a.y - b.y}; }
Point operator * (Point a, int b){ return (Point){a.x * b, a.y * b}; }
Point operator / (Point a, int b){ return (Point){a.x / b, a.y / b}; }
double theta(Point a){ return atan2(a.y, a.x); }
double dis(Point a, Point b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
int bl[maxn];
ll calc(int k, int x) {
int res = 1;
for(int i = 0; i < 3; i ++)
if(x != i) res *= sum[k][i];
return res;
}
void solve(int u){
int m = 0;
for(int i = 1 ; i <= n ; ++i){
if(i == u) continue;
b[++m] = a[i];
}
for(int i = 1 ; i <= m ; ++i){
b[i].x -= a[u].x, b[i].y -= a[u].y;
b[i].k = theta(b[i]);
if(b[i].k <= 0) b[i].k += pi;
}
sort(b + 1, b + 1 + m);
memset(sum, 0, sizeof(sum));
for(int i = 1 ; i <= m ; ++i) {
if(b[i].y < 0 || (b[i].y == 0 && b[i].x > 0)) {
bl[i] = 0;
} else {
bl[i] = 1;
}
sum[bl[i]][b[i].c]++;
}
for(int i = 1 ; i <= m ; ++i){
sum[bl[i]][b[i].c]--;
ans += calc(0, b[i].c) * calc(1, a[u].c);
ans += calc(1, b[i].c) * calc(0, a[u].c);
sum[bl[i] ^= 1][b[i].c]++;
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
scanf("%d", &n);
for(int i = 1 ; i <= n ; ++i){ scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].c); }
for(int i = 1 ; i <= n ; ++i) solve(i);
printf("%lld\n", ans / 4);
return 0;
}