现在的位置: 首页 > 综合 > 正文

BZOJ 1914: [Usaco2010 OPen]Triangle Counting 数三角形

2018年04月24日 ⁄ 综合 ⁄ 共 1307字 ⁄ 字号 评论关闭

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)。下图是由贝西视角所绘出的图示。 

Input

第一行:一个整数: N 第2到第N+1行: 每行两个整数X_i,Y_i,表示每只牛的坐标

Output

* 第一行: 一行包括一个整数,表示“黄金三角形的数量”

Sample Input

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;
}

抱歉!评论已关闭.