1132: [POI2008]Tro
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1663 Solved: 558
[ Submit][ Status][ Discuss]
Description
平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和 N<=3000
Input
第一行给出数字N,N在[3,3000] 下面N行给出N个点的坐标,其值在[0,10000]
Output
保留一位小数,误差不超过0.1
Sample Input
5
0 0
1 2
0 2
1 0
1 1
Sample Output
7.0
考虑先暴力每一个点(X, Y)
对于当前点(X, Y),暴力其它所有点(x, y),将每个点先处理为(x', y') = (x-X, y-Y)
这样当前点对答案的贡献就为(还要除以2)
所有点按x从小到大排序,然后按顺序枚举(X, Y),以(X, Y)为源点后,剩下点再按幅角排序,那么上面公式的每一项就一定都为正,就可以去掉绝对值
化简公式有
对于yb'和xb'求前缀和,就可以O(n)算出贡献了
复杂度O(n*(nlogn+n))=O(n²logn)
注意上面公式算的是四边形面积,所以答案要除以2,还有要去重
#include<stdio.h>
#include<algorithm>
using namespace std;
#define LL long long
int X, Y;
typedef struct Point
{
int x, y;
bool operator < (const Point &b) const
{
if((x-X)*(b.y-Y)>(y-Y)*(b.x-X))
return 1;
return 0;
}
}Point;
Point s[6005];
bool comp(Point a, Point b)
{
if(a.x<b.x || a.x==b.x && a.y<b.y)
return 1;
return 0;
}
int main(void)
{
LL ans;
int n, i, j, sy, sx;
scanf("%d", &n);
for(i=1;i<=n;i++)
scanf("%d%d", &s[i].x, &s[i].y);
sort(s+1, s+n+1, comp);
ans = 0;
for(i=1;i<=n;i++)
{
X = s[i].x, Y = s[i].y;
for(j=i+1;j<=n;j++)
s[n+j-i].x = s[j].x, s[n+j-i].y = s[j].y;
sort(s+n+1, s+n+n-i+1);
sx = sy = 0;
for(j=n+1;j<=n+n-i;j++)
{
ans += (LL)(s[j].y-Y)*sx-(LL)(s[j].x-X)*sy;
sx += s[j].x-X;
sy += s[j].y-Y;
}
}
if(ans%2==0)
printf("%lld.0\n", ans/2);
else
printf("%lld.5\n", ans/2);
}