• POJ 2079 最大三角形面积(凸包)


    Triangle

    Description

    Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices are from the given points.

    Input

    The input consists of several test cases. The first line of each test case contains an integer n, indicating the number of points on the plane. Each of the following n lines contains two integer xi and yi, indicating the ith points. The last line of the input is an integer −1, indicating the end of input, which should not be processed. You may assume that 1 <= n <= 50000 and −104 <= xi, yi <= 104for all i = 1 . . . n.

    Output

    For each test case, print a line containing the maximum area, which contains two digits after the decimal point. You may assume that there is always an answer which is greater than zero.

    Sample Input

    3
    3 4
    2 6
    2 7
    5
    2 6
    3 9
    2 0
    8 0
    6 5
    -1

    Sample Output

    0.50
    27.00

    Source

    凸包三角:求N个点组成的三角形的最大面积?

    思路:

    不难想到最大三角形一定由凸包的顶点构成,难点在于怎么搜索。O(N^3)枚举会超时,旋转卡壳法O(N^2)解决问题。

    点的移动:先固定一条边(红色实线),然后依次搜索第3个顶点1st,三角形面积必然是先增后减的,一旦发现开始减小了,立即终止搜索,转而移动固定边。

    边的移动:固定边的移动也有讲究,固定边两点的跨度用add表示的话,add不一定是1,最大可达到(N + 1)/2,于是将此add也枚举一遍即可。

    代码:

      1 #include "cstdio"
      2 #include "map"
      3 #include "cmath"
      4 #include "queue"
      5 #include "vector"
      6 #include "string"
      7 #include "cstring"
      8 #include "iostream"
      9 #include "algorithm"
     10 #define db double
     11 #define ll long long
     12 #define vec vector<ll>
     13 #define mt  vector<vec>
     14 #define ci(x) scanf("%d",&x)
     15 #define cd(x) scanf("%lf",&x)
     16 #define cl(x) scanf("%lld",&x)
     17 #define pi(x) printf("%d
    ",x)
     18 #define pd(x) printf("%f
    ",x)
     19 #define pl(x) printf("%lld
    ",x)
     20 //#define rep(i, x, y) for(int i=x;i<=y;i++)
     21 #define rep(i,n) for(int i=0;i<n;i++)
     22 const int N   = 1e5 + 5;
     23 const int mod = 1e9 + 7;
     24 const int mOD = mod - 1;
     25 const db  eps = 1e-10;
     26 const db  PI  = acos(-1.0);
     27 const int inf=0x3f3f3f3f;
     28 using namespace std;
     29 struct P
     30 {
     31     db x, y;
     32     P() {}
     33     P(db x, db y) : x(x), y(y) {}
     34     P operator + (P p){ return P(x + p.x, y + p.y); }
     35     P operator - (P p){ return P(x - p.x, y - p.y); }
     36     P operator * (db d){ return P(x*d, y*d); }
     37     bool operator < (const P& a) const
     38     {
     39         if (x != a.x) return x < a.x;
     40         else return y < a.y;
     41     }
     42     db dot(P p) { return x*p.x + y*p.y; }
     43     db det(P p) { return x*p.y - y*p.x; }
     44 };
     45 
     46 P p[N];
     47 // 向量AB 与 AC 的叉积 如果叉积大于0,那么C在向量AB的逆时针方向,叉积小于0则在AB的顺时针方向。如果叉积等于0,则ABC共线。
     48 db cross(P A, P B, P C) {return (B - A).det(C - A); }
     49 // AB和AC构成的平行四边形面积
     50 db Area(P A, P B, P C)  {return abs(cross(A, B, C)); }
     51 // 求凸包
     52 vector <P> ch(P *ps, int n)
     53 {
     54     sort(ps, ps + n);
     55     int k = 0;   // 凸包的顶点数
     56     vector <P> qs(n * 2);   // 构造中的凸包
     57     for (int i = 0; i < n; ++i)
     58     {
     59         while (k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0)
     60             --k;
     61         qs[k++] = ps[i];
     62     }
     63     for (int i = n - 2, t = k; i >= 0; --i)
     64     {
     65         while (k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0)
     66             --k;
     67         qs[k++] = ps[i];
     68     }
     69     qs.resize(k - 1);
     70     return qs;
     71 }
     72 
     73 int main()
     74 {
     75     int n;
     76     while (~scanf("%d", &n) && n > 0)
     77     {
     78         for(int i = 0; i < n; ++i) cd(p[i].x),cd(p[i].y);
     79         vector <P> ps = ch(p, n);
     80         n = ps.size();
     81         db ans = 0;
     82         for(int ad = 1; ad < (n + 1) / 2; ++ad)
     83         {
     84             int k = (ad + 1) % n;
     85             for(int i = 0; i < n; ++i)
     86             {
     87                 int j = (i + ad) % n;
     88                 db prev = Area(ps[i], ps[j], ps[k]);
     89                 for(++k; k != j && k != i; ++k)
     90                 {
     91                     if (k == n) k = 0;
     92                     db cur = Area(ps[i], ps[j], ps[k]);
     93                     ans = max(ans, prev);
     94                     if (cur <= prev) break;    // 达到极值
     95                     prev = cur;
     96                 }
     97                 --k;                    // 退出循环时,其实k已经超了一个,这里减回来
     98                 if(k == -1) k += n;
     99             }
    100         }
    101         printf("%.2f
    ", ans / 2);
    102     }
    103     return 0;
    104 }
  • 相关阅读:
    leetcode@ [300] Longest Increasing Subsequence (记忆化搜索)
    leetcode@ [200] Number of Islands
    JMETER压力测试报错:JAVA.NET.BINDEXCEPTION: ADDRESS ALREADY IN USE: CONNECT
    压力测试报告模版
    Jmeter学习—004—使用代理录制脚本—HTTP代理服务器(APP、web皆可)
    怎么用fiddler抓APP的包
    Jmeter录制脚本过程及Could not create script recorder报错、您的连接不是私密连接报错
    Github使用说明 --整理者米米
    Anaconda详细安装使用教程
    运用MQTT-JMeter插件测试MQTT服务器性能
  • 原文地址:https://www.cnblogs.com/mj-liylho/p/8431453.html
Copyright © 2020-2023  润新知