码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj-1132 Tro

时间:2015-07-31 09:07:45      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:bzoj   计算几何   

题意:

给出n个点,求这n个点组成的所有三角形的面积和;

n<=3000;


题解:

这道题O(n^3)枚举三角形时间复杂度是无法承受的;

所以考虑枚举一条边,多个三角形一起来计算,复杂度在O(n^2)的级别;

求三角形面积可以底乘高的面积公式,也可以上叉积;

如果采用底乘高的方法,求出所有的点到直线的距离之和,也是可以O(1)得到当前的解的;

但是求距离之和这一步必然是O(n)的,也难以转移到下一个底上去;

而叉积的方法则是化简叉积的式子,可以把点的坐标提出来,加和一起运算;

但是叉积求得的是有向面积,这东西卡了我半天;

实际上实现是这样的:

枚举第一个点,取第一个点右上方的点集,将点集按与第一个点的斜率大小排序,然后枚举第二个点求解;

这样每个面积只求了一遍,而且因为斜率有序,所以所有三角形都是正的面积了;

因为排了序,所以时间复杂度O(n^2 logn);

(我居然因为保留两位小数WA了一晚上!!)


代码:


#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 3100
using namespace std;
typedef long long ll;
struct Point
{
	ll x,y;
	double slope;
	friend bool operator <(Point a,Point b)
	{
		if(a.x==b.x)
		return a.y<b.y;
		return a.x<b.x;
	}
	friend Point operator -(Point a,Point b)
	{
		return (Point){a.x-b.x,a.y-b.y};
	}
	friend int operator *(Point a,Point b)
	{
		return a.x*b.y-a.y*b.x;
	}
}a[N],t[N],O;
bool cmp(Point a,Point b)
{
	return a.slope>b.slope;
}
int main()
{
	int n,m,i,j,k;
	ll ans,sx,sy,tx,ty;
	scanf("%d",&n);
	for(i=1,sx=sy=0;i<=n;i++)
	{
		scanf("%d%d",&a[i].x,&a[i].y);
		sx+=a[i].x,sy+=a[i].y;
	}
	sort(a+1,a+1+n);
	for(i=1,ans=0;i<=n;i++)
	{
		sx-=a[i].x,sy-=a[i].y;
		tx=sx,ty=sy;
		O=a[i];
		memcpy(t+i+1,a+i+1,sizeof(Point)*(n-i));
		for(j=i+1;j<=n;j++)
		{
			if(t[j].x==O.x)
				t[j].slope=1e10;
			else
				t[j].slope=(double)(t[j].y-O.y)/(t[j].x-O.x);
		}
		sort(t+i+1,t+n+1,cmp);
		for(j=i+1;j<n;j++)
		{
			Point v=t[j]-a[i];
			tx-=t[j].x,ty-=t[j].y;
			ans+=tx*v.y-ty*v.x+(n-j)*(a[i].y*v.x-a[i].x*v.y);
		}
	}
	printf("%lld.%d",ans>>1,ans&1?5:0);
	return 0;
}




bzoj-1132 Tro

标签:bzoj   计算几何   

原文地址:http://blog.csdn.net/ww140142/article/details/47164581

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!