[POI2008]Triangles

题目大意:
  平面直角坐标系上有n个点,问以这n个点为顶点的不同的三角形的面积和是多少?

思路:
  很容易想到一个O(n^3)的暴力,枚举三个点,用海龙公式求一下面积和即可,这样做是40分。
  标算的复杂度是O(n^2 log n),
  首先对所有的点按照位置的左右排序,
  按顺序枚举每一个点i,并将其作为三角形的一个顶点。
  对于顺序在i后面的点关于点i极角排序,并按照极角序枚举每一个点j。
  三角形面积的两倍我们可以用叉积来求。
  为了不枚举第三个顶点,我们可以算一下后缀和。
  这题会爆double,由于小数部分要么是.0要么是.5,我们可以用long long来存一下,最后特判一下奇数偶数即可。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 typedef long long int64;
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=3000;
13 struct Point {
14     int x,y;
15     Point operator - (const Point &another) const {
16         return (Point){x-another.x,y-another.y};
17     }
18     int64 operator * (const Point &another) const {
19         return (int64)x*another.y-(int64)y*another.x;
20     }
21 };
22 Point p[N],t[N];
23 inline bool cmp1(const Point &a,const Point &b) {
24     if(a.y==b.y) return a.x<b.x;
25     return a.y<b.y;
26 }
27 inline bool cmp2(const Point &a,const Point &b) {
28     return a*b>0;
29 }
30 int main() {
31     int n=getint();
32     for(register int i=0;i<n;i++) {
33         p[i]=(Point){getint(),getint()};
34     }
35     std::sort(&p[0],&p[n],cmp1);
36     int64 ans=0;
37     for(register int i=0;i<n;i++) {
38         int cnt=0;
39         for(register int j=i+1;j<n;j++) {
40             t[++cnt]=p[j]-p[i];
41         }
42         std::sort(&t[1],&t[cnt+1],cmp2);
43         Point sum=(Point){0,0};
44         for(register int j=cnt;j;j--) {
45             ans+=sum*t[j];
46             sum=sum-t[j];
47         }
48     }
49     printf("%lld.%c\n",ans>>1,(ans&1)?'5':'0');
50     return 0;
51 }

 

posted @ 2017-10-31 13:25  skylee03  阅读(132)  评论(0编辑  收藏  举报