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