三角形计数

三角形计数
时间限制: 3 Sec 内存限制: 8 MB

题目描述
【背景】
Day1T1当然是又裸又水的题了怎么会有背景呢。
【题目描述】
给定n个点的坐标(0<=xi,yi<=10000)求选出任意三个点能组成的三角形的总面积。
输入
第一行n表示点数。接下来每行两个数xi,yi表示点的坐标。
输出
一行一个浮点数保留一位小数表示面积和。
样例输入
5
0 0
1 2
0 2
1 0
1 1
样例输出
7.0
提示
【样例解释】

【数据范围】

数据为随机生成。
T1 xi yi为整数
T1 第6~8个测试点满足:对于所有满足xmin<=xi<=xmax且ymin<=yi<=ymax的点都会出现在数据中且没有重复的点。
例如:(6,6) (6,7) (6,8) (7,6) (7,7) (7,8) (8,6) (8,7) (8,8)
题解:
等价于求
i = 1 n j = i + 1 n k = j + 1 n | ( x j x i ) ( y k y i ) ( x k x i ) ( y j y i ) |

枚举 i 并将 i 所在的点看作原点,将所以向量按斜率排序,去掉绝对值并化简,假设新坐标为 X i Y i
等价于求
j = i + 1 n k = j + 1 n X j Y k X k Y j

使用前缀和计算即可。
C o d e :

#include<bits/stdc++.h>  
#define ll long long 
using namespace std; 
int n; 
ll sumx,sumy,ans; 
struct node  
{ 
    int x,y; 
}p[3005]; 
struct line 
{ 
    int x,y; 
    double k; 
}b[3005]; 
bool cmp1(node p1,node p2) 
{ 
    return p1.y>p2.y; 
} 
bool cmp2(line l1,line l2) 
{ 
    return l1.k<l2.k; 
} 
int main() 
{ 
    scanf("%d",&n); 
    for(int i=1;i<=n;i++) 
        scanf("%d%d",&p[i].x,&p[i].y); 
    sort(p+1,p+n+1,cmp1); 
    for(int i=3;i<=n;i++) 
    { 
        for(int j=1;j<i;j++) 
        { 
            b[j].x=p[j].x-p[i].x; 
            b[j].y=p[j].y-p[i].y; 
            b[j].k=atan2(b[j].y,b[j].x); 
        } 
        sort(b+1,b+i,cmp2); 
        sumx=b[1].x;sumy=b[1].y; 
        for(int j=2;j<i;j++) 
        { 
            ans+=(ll)sumx*b[j].y-(ll)sumy*b[j].x; 
            sumx+=b[j].x;sumy+=b[j].y; 
        } 
    } 
    if(ans%2==0)printf("%lld.0\n",ans/2); 
    else printf("%lld.5\n",ans/2); 
} 

猜你喜欢

转载自blog.csdn.net/qq_34531807/article/details/81050237