链接:https://ac.nowcoder.com/acm/contest/327/A
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
平面上有n个点,问:平面上所有三角形面积第k大的三角形的面积是多少?
输入描述:
第一行T,表示样例的个数。
对于每一组样例,第一行两个整数n和k,
接下来n行,每行两个整数x,y表示点的坐标
T<=80
3<=n<=100
-109<=x,y<=109
对于每一组样例,保证任意两点不重合,且能构成的三角形的个数不小于k
输出描述:
对于每一组样例,输出第k大三角形的面积,精确到小数点后两位(四舍五入)。
示例1
说明
样例中一共能构成3个三角形,面积分别为0.5,0.5,和1,面积第3大的为0.5
由于题目条件,x,y坐标的绝对值均在1e9以下,面积可能会到达1e18,所以无法用double储存。
三角形的面积等于相邻两边叉积的一半,所以三角形面积的两倍一定是整数,我们可以用long long来储存,最后特判输出”.00”或”.50”。
对于找第k大,时间复杂读为O(n),可以利用快排的思想或者利用nth_elemen
这里附加nth_elemen容器的用法
它的用法是nth_element(a+l,a+k,a+r)
这样它会使a这个数组中区间(l,r)(l,r)内的第kk大的元素处在第kk个位置上(相对位置)
不过根据网友的实验,貌似在vs上是有序的,不过在dev中是无序的
时间复杂度:O(n)
#include<iostream> #include<algorithm> using namespace std; int main() { static int a[15] = {0, 1, 2, 5, 7, 3, 4, 1}; nth_element(a + 1, a + 4, a + 8); for (int i = 1; i <= 8; i++) printf("%d ", a[i]); printf(" "); return 0; }
输出结果为
1,1,2,3,5,4,7,0
下面是该题的代码(暴力的)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; ll b[1000000]; struct point { ll x,y; } c[101]; ll squ(ll x1,ll y1,ll x2,ll y2,ll x3,ll y3) { return (x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2); } int main() { ll t,n,k; cin>>t; while(t--) { cin>>n>>k; for(int i=1; i<=n; i++) cin>>c[i].x>>c[i].y; ll s; int flag=0; for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { for(int m=j+1; m<=n; m++) { s=squ(c[i].x,c[i].y,c[j].x,c[j].y,c[m].x,c[m].y); if(s!=0) { b[flag]=abs(s); flag++; } } } } nth_element(b,b+flag-k,b+flag); cout<<b[flag-k]/2; if(b[flag-k]%2) cout<<".50"<<endl; else cout<<".00"<<endl; } return 0; }