处女座的签到题(我就来溜溜处女座)

处女座的签到题
链接:https://ac.nowcoder.com/acm/contest/327/A
来源:牛客网

题目描述
平面上有n个点,问:平面上所有三角形面积第k大的三角形的面积是多少?
输入描述:
第一行T,表示样例的个数。
对于每一组样例,第一行两个整数n和k,
接下来n行,每行两个整数x,y表示点的坐标
T<=80
3<=n<=100
-10^9 <=x,y<=10^9
对于每一组样例,保证任意两点不重合,且能构成的三角形的个数不小于k
输出描述:
对于每一组样例,输出第k大三角形的面积,精确到小数点后两位(四舍五入)。
示例1
输入
1
4 3
1 1
0 0
0 1
0 -1
输出
0.50
说明
样例中一共能构成3个三角形,面积分别为0.5,0.5,和1,面积第3大的为0.5

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
 
struct Point{
    long long x;
    long long y;
}point[105];//n的最大取值是100,但是这里取值最好要大于100 
 
long long s[1000000];//大数组最好开在外面

int main()
{
    int T;
    scanf("%d",&T);//同一个源文件里面最好不要同时出现cin和scanf 
    while(T--){
    	int n,K;
        scanf("%d%d",&n,&K);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&point[i].x,&point[i].y);
        int i,j,k;
        long long Count=0;//将Count设为全局变量就报WA 
        for(i=1;i<=n-2;i++){//这里i,j,k的最大取值都可以为n,由于是三重循环,i=n-1之后的取值都会因为k的最大取值而被中断 
            for(j=i+1;j<=n-1;j++){
                for(k=j+1;k<=n;k++){
                	long long m=0; // 将m设为全局变量就报WA
                    m = (point[j].x-point[i].x)*(point[k].y-point[i].y)-(point[k].x-point[i].x)*(point[j].y-point[i].y);
                    if(m == -0 || m == 0){
                        continue;
                    }
                    if(m < 0){
                        m = -m;
                    }
                    if(m) s[++Count] = m;//这个地方用Count++就错了 
                }
            }
        }
 		K = Count-K+1;
 		nth_element(s+1,s+K,s+Count+1);
        long long t=s[K];
        if(t%2==0)
            printf("%lld.00\n",t/2);
        else
            printf("%lld.50\n",t/2);
       }
    return 0;  
}

还要注意题目的意思,它是说先保留两位小数再进行四舍五入,也就是说,小数点后面的数字只能是00和50,即0.00和0.50,当初被这里狠狠的坑了一把。

然后,这里需要用到nth_element(a+l,a+k,a+r),包含在 < algorithm > 头文件,这个函数旨在搜索第K元,从0开始,最大的是n+1元,所以这里要将K倒过来处理一下,目测sort()不行,因为这个s数组之前存了n * n*n的数据,则加sort的时间复杂度为n * n * n * log(n * n * n),广播消息说要在线性时间内找到第K元,故sort()超时。

以下内容参考了yxwkaifa的博文,原文链接:https://www.cnblogs.com/yxwkf/p/5233716.html
nth_element()函数
头文件:#include< algorithm >
作用:nth_element作用为求第n大的元素,并把它放在第n位置上,下标是从0開始计数的,也就是说求第0小的元素就是最小的数。nth_element()函数无返回值。
举例:如:a[start,end]元素区间。排序后a[n]就是数列中第n+1大的数(下标从0開始计数)。要注意的是a[start,n),a[n,end]内的大小顺序还不一定。仅仅能确定a[n]是数列中第n+1大的数。当然a[start,n)中的数肯定不大于a[n,end]中的数。
思想快排,当然这里不能用quicksort,原因与sort同理。

叉积计算三角形面积公式:(axby-bxay)/2

关于利用叉积计算面积那一块其实可以写个函数,但是,将近n^3次的调用可能会发生错误,就没用,实际上这个自定义函数的方法是可行的。另外,为了不利用强制转换,采取统一变量方式,故而,先不除二。以后这种技巧可能会经常用到。整场比赛,这个题我大概做了4个多小时,暴露了我很多问题,是道良心题。虽然我更想要温暖就是了!【手动滑稽】

最后,其实可以不用考虑三点一线的问题,原因如下:
1.若三点共线,面积必为0,考虑删掉这个数据,或者不删掉;
2.如果不删掉,对于第K元其实没有什么影响,因为0始终是最小的。

所以,本题的题意是从n个点中选取3个点,计算他们的面积,找到第K大的,总数为n*(n-1)*(n-2)/6。

猜你喜欢

转载自blog.csdn.net/weixin_43227938/article/details/86643748