Description
在一只大灰狼偷偷潜入Farmer Don的牛群被群牛发现后,贝西现在不得不履行着她站岗的职责。从她的守卫塔向下瞭望简直就是一件烦透了的事情。她决定做一些开发智力的小练习,防止她睡着了。想象牧场是一个X,Y平面的网格。她将N只奶牛标记为1…N (1 <= N <= 100,000),每只奶牛的坐标为X_i,Y_i (-100,000 <= X_i <= 100,000;-100,000 <= Y_i <= 100,000; 1 <= i <=N)。然后她脑海里想象着所有可能由奶牛构成的三角形。如果一个三角形完全包含了原点(0,0),那么她称这个三角形为“黄金三角形”。原点不会落在任何一对奶牛的连线上。另外,不会有奶牛在原点。给出奶牛的坐标,计算出有多少个“黄金三角形”。顺便解释一下样例,考虑五只牛,坐标分别为(-5,0),
(0,2), (11,2), (-11,-6), (11,-5)。下图是由贝西视角所绘出的图示。
(0,2), (11,2), (-11,-6), (11,-5)。下图是由贝西视角所绘出的图示。
Input
第一行:一个整数: N 第2到第N+1行: 每行两个整数X_i,Y_i,表示每只牛的坐标
Output
* 第一行: 一行包括一个整数,表示“黄金三角形的数量”
Sample Input
5
-5 0
0 2
11 2
-11 -6
11 -5
-5 0
0 2
11 2
-11 -6
11 -5
Sample Output
5
题解
计算几何,正难则反的思想。答案就是所有三角形去掉非黄金三角形。
先极角排序,对于某个点x,其与原点连线所在直线将平面划分为两部分,若一个部分有t个点,在这t个中任取2个与x显然不构成黄金三角形,,画图可知对于每个点只统计某个方向的半平面内的点就能不重不漏。具体可以用一个指针旋转半平面。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<algorithm> #define ll long long #define pi acos(-1.0) using namespace std; int n; struct dian{int x,y;double dgr;} d[100005]; ll tot,del; bool operator < (dian i,dian j) {return i.dgr<j.dgr;} ll operator * (dian i,dian j) {return (ll)i.x*j.y-(ll)i.y*j.x;} void init() { scanf("%d",&n); int i; for(i=1;i<=n;i++) {scanf("%d%d",&d[i].x,&d[i].y); d[i].dgr=atan2(d[i].y,d[i].x); } sort(d+1,d+n+1); tot=(ll)n*(n-2)*(n-1)/6; } void work() { int i,w=1,ct=0; for(i=1;i<=n;i++) {while(w%n+1!=i&&d[i]*d[w%n+1]>=0) {w=w%n+1;ct++;} del+=(ll)ct*(ct-1)/2; ct--; } printf("%lld\n",tot-del); } int main() { init(); work(); return 0; }