HDU

来源:互联网 发布:软件低通滤波算法 编辑:程序博客网 时间:2024/06/06 08:44

传送门:HDU5784

题意:给出n个不重合的点,问能形成多少个不同的锐角三角形。

思路:统计出所有的锐角,直角,钝角的数量,假设分别为A,B,C,由于一个钝角或者直角三角形中也包含两个锐角,因此答案为(A - 2 * (B + C)) / 3.

下面考虑如何快速求解:

枚举每一个顶点,算出所有向量,极角排序后再枚举每一个向量,用类似尺取的方法找到逆时针方向能和该向量形成最大锐角和钝角的向量的位置,计算对答案的贡献,注意每次开始要跳过所有同向的向量。

详细题解:点击打开链接

几种极角排序方法:点击打开链接

代码:

#include<bits/stdc++.h>#define ll long long#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int> P;const int MAXN = 2010;struct point{ll x, y;point(ll _x = 0, ll _y = 0) : x(_x), y(_y) {}point operator - (const point &a) const{return point(x - a.x, y - a.y);}ll operator * (const point &a) const{return x * a.y - y * a.x;}ll operator ^ (const point &a) const{return x * a.x + y * a.y;}bool sign() const{return y > 0 || (y == 0 && x > 0);}bool operator < (const point &a) const{if(sign() == a.sign()) return (*this) * a > 0;return sign() > a.sign();}}p[MAXN], tmp[MAXN << 1];int main(){int n;while(cin >> n){int ans = 0;for(int i = 0; i < n; i++)scanf("%lld %lld", &p[i].x, &p[i].y);for(int i = 0; i < n; i++){int cnt = 0;for(int j = 0; j < n; j++)if(i != j)tmp[cnt++] = p[j] - p[i];sort(tmp, tmp + cnt);for(int j = 0; j < cnt; j++) tmp[j + cnt] = tmp[j];int id1, id2, id3;//同向向量、锐角、钝角对应的最大下标 id1 = id2 = id3 = 0; for(int j = 0; j < cnt; j++){while(id1 < cnt * 2 && (tmp[j] * tmp[id1]) == 0 && (tmp[j] ^ tmp[id1]) > 0) id1++;id2 = max(id2, id1);while(id2 < cnt * 2 && (tmp[j] * tmp[id2]) > 0 && (tmp[j] ^ tmp[id2]) > 0) id2++;id3 = max(id3, id2);while(id3 < cnt * 2 && (tmp[j] * tmp[id3]) > 0 && (tmp[j] ^ tmp[id3]) < 0) id3++;ans += id2 - id1;ans -= 2 * (id3 - id2);}}printf("%d\n", ans / 3);} return 0;}