[gym101047K Training with Phuket's larvae] 给定N条边求能组成三角形的最小面积

来源:互联网 发布:金融数据挖掘 马超群 编辑:程序博客网 时间:2024/06/01 07:32

[gym101047K Training with Phuket’s larvae] 给定N条边求能组成三角形的最小面积

题目链接:[gym101047K Training with Phuket’s larvae]
题意描述:给定N条边,(N2000), 从这些边中选出三条边组成面积最小的三角形,最小面积是多少。如果都不能形成三角形,输出-1。
解题思路
首先,对所有的边进行排序,然后遍历两条边a, b,(假设a<b),然后二分求第三条边c的边界,即ba<c<a+b。其实可以发现三角形的最小面积只可能是c 的上边界和下边界。
因为三角形两边边长固定的情况下,第三条边尽可能短,或者第三条边尽可能长都会使得面积变小。换句话说,就是使得这三角形尽可能….

#include <queue>#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;//#pragma comment(linker, "/STACK:1024000000,1024000000")#define FIN             freopen("input.txt","r",stdin)#define FOUT            freopen("output.txt","w",stdout)#define fst             first#define snd             secondtypedef __int64  LL;typedef pair<int, int> PII;const double eps = 1e-8;const int MAXN = 2000 + 5;const int INF  = 0x3f3f3f3f;int T, N, M;double A[MAXN];inline int sgn (double x, double y) {    if (fabs (x - y) == 0) return 0;    return x < y ? -1 : 1;}inline double getArea (double a, double b, double c) {    double x = (a + b + c) / 2.0;    return sqrt (x * (x - a) * (x - b) * (x - c) );}int main() {#ifndef ONLINE_JUDGE    FIN;    // FOUT;#endif // ONLINE_JUDGE    double a, b, c, res;    scanf ("%d", &T);    while (T --) {        scanf ("%d", &N);        for (int i = 0; i < N; i++) {            scanf ("%lf", &A[i]);        }        sort (A, A + N);        res = (double) INF;        for (int i = 0; i < N; i++) {            a = A[i];            for (int j = i + 1; j < N; j++) {                b = A[j];                int low = upper_bound (A + j + 1, A + N, b - a) - A;                int high = lower_bound (A + j + 1, A + N, a + b) - A - 1;                if (low < N) {                    c = A[low];                    if (sgn (a + b, c) <= 0 || sgn (a + c, b) <= 0 || sgn (b + c, a) <= 0) continue;                    res = min (res, getArea (a, b, c) );                }                if (high > low) {                    c = A[high];                    if (sgn (a + b, c) <= 0 || sgn (a + c, b) <= 0 || sgn (b + c, a) <= 0) continue;                    res = min (res, getArea (a, b, c) );                }            }        }        if (sgn (res, (double) INF) == 0) {            printf ("-1\n");        } else {            cout << fixed << setprecision (8) << res << "\n";        }    }    return 0;}

拓展一下
在挑战竞赛上17页有一个求最大周长的题目。作者只是提到了一个Nlog(N)的做法让读者思考。
最大周长
O(∩_∩)O哈哈~
我的做法:首先对边长排序。然后呢,要使得周长最大,主要取相邻的三条满足条件的边。这样的复杂度就是Nlog(N)。

0 0