2016多校训练Contest5: 1004 How Many Triangles hdu5784

Problem Description
Alice has n points in two-dimensional plane. She wants to know how many different acute triangles they can form. Two triangles are considered different if they differ in at least one point.
 

Input
The input contains multiple test cases.
For each test case, begin with an integer n,
next n lines each contains two integers  xi  and  yi .
3n2000
0xi,yi1e9
Any two points will not coincide.
 

Output
For each test case output a line contains an integer.
 

Sample Input
  
  
3 1 1 2 2 2 3 3 1 1 2 3 3 2 4 1 1 3 1 4 1 2 3
 

Sample Output
  
  
0 1 2

计算几何题目。我们枚举每个点作为角的顶点,然后计算以这个角为顶点的角有多少锐角和钝角【不包括0°和180°】

对于这个点,将其他点极角排序,然后用两个指针扫描,因为排过序了,所以扫描这里是O(n)的

记得扫描的时候多记录几个值来去除0°和180°的角,扫描的时候要判断不能扫过180°



这题我刚写完用官方数据跑了一下是20S

然后改了一个多小时想着先交一发到hdu就直接就A了,而且就跑了2.8S。exm???

这是数据改了还是怎么回事= =我交上去的那份本机跑也还是20多S

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define N 5000
typedef struct
{
     long long x;
     long long y;
}point;
point points[N],px[N]; //点集
//计算两点之间距离
inline long long dis(point a, point b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
//通过矢量叉积求极角关系(p0p1)(p0p2)
//k > 0 ,p0p1在p0p2顺时针方向上
inline long long check(point p1, point p0, point p2)
{
     return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
inline long long multi(point p0, point p1, point p2)
{
     return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
inline bool cmp(point a,point b)
{
	if ((a.y-points[0].y)*(b.y-points[0].y)<=0)
	{
		if ((a.y-points[0].y)==0 && (b.y-points[0].y)==0) return (a.x-points[0].x)<(b.x-points[0].x);
		if ((a.y-points[0].y)>0 || (b.y-points[0].y)>0) return (a.y-points[0].y)<(b.y-points[0].y);
	}
    return (multi(points[0],a,b)>0);

}
long long ans1,ans2;
inline void convex_hull(int n)
{
     int i,j,k,d;
     double miny=points[0].y;
     int index=0;
     for(i=0;i<n;i++)
     {
     	 for(j=0;j<n;j++)
     	 	points[j]=px[j];
	     point temp;
	     temp=points[i];
	     points[i]=points[0];
	     points[0]=temp;
	     sort(points+1,points+n,cmp); //p[1:n-1]按相对p[0]的极角从小到大排序
	     for(j=n;j<n*2-1;j++)
	     	points[j]=points[j-n+1];
	     int k1=1,kk=1,k2=2,k3=2;
	     while(k1<=n-1)
	     {
	     	  if(kk<=k1)
	     	       kk=k1+1;
	          long long d=multi(points[0],points[k1],points[kk]);
	          while(d==0&&kk<=n-1&&check(points[k1],points[0],points[k2])>0)
	          {
	                kk++;
	                d=multi(points[0],points[k1],points[kk]);
	          }
	     	  if(k2<kk)
	     	       k2=kk;
	          d=check(points[k1],points[0],points[k2]);
	          while(d>0&&k2<=n*2-2&&multi(points[k1],points[k2],points[0])>0)
	          {
	                k2++;
	                d=check(points[k1],points[0],points[k2]);
	          }
	          ans1+=k2-kk;
	          if(k3<k2)
			  	k3=k2;
	          d=check(points[k1],points[0],points[k3]);
	          while(d<=0&&k3<=n*2-2&&multi(points[k1],points[k3],points[0])>0)
	          {
	                k3++;
	                d=check(points[k1],points[0],points[k3]);
	          }
	          ans2+=k3-k2;
	          k2--;
	          k1++;
	     }
	 }
}
int main()
{
//	freopen("1004.in","r",stdin);
//	freopen("1004.ans","w",stdout);
     int i,j,n;
     double sum,area;
     while(scanf("%d",&n)!=EOF)
     {
          if(n==0)
		       break;
          for(i=0;i<n;i++)
          {
               scanf("%I64d%I64d",&points[i].x,&points[i].y);
               px[i]=points[i];
          }
          ans1=0;
          ans2=0;
          convex_hull(n);
       //   printf("%I64d %I64d %I64d\n",ans1,ans2,(ans1-(long long)2*ans2)/(long long)3);
          printf("%I64d\n",(ans1-(long long)2*ans2)/(long long)3);
     }
     return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值