码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 11168(凸包、直线一般式)

时间:2019-06-02 00:50:01      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:clu   def   int()   pac   for   namespace   poi   iostream   int   

要点

  • 找凸包上的线很显然
  • 但每条线所有点都求一遍显然不可行,优化方法是:所有点都在一侧所以可以使用直线一般式的距离公式\(\frac{|A* \sum{x}+B* \sum{y}+C*n|}{\sqrt {A^2+B^2}}\)\(O(1)\)算出总距离
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

typedef double db;
const int maxn = 1e4 + 5;
const db eps = 1e-8;

int dcmp(db x) {
    if (fabs(x) < eps)  return 0;
    return x > 0 ? 1 : -1;
}

int T, n, cnt;
struct Point {
    db x, y;
    
    Point(){}

    Point(db a, db b):x(a), y(b){}

    bool operator < (const Point &rhs) const {
        if (dcmp(x - rhs.x) != 0)   return dcmp(x - rhs.x) < 0;
        return dcmp(y - rhs.y) < 0;
    }
}p[maxn];
Point v[maxn];

db Cross(Point A, Point B) {//顺时针转动则叉积为负
    return A.x * B.y - A.y * B.x;
}

Point operator - (Point A, Point B) {
    return Point(A.x - B.x, A.y - B.y);
}

bool operator == (Point A, Point B) {
    return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;
}

void ConvexHull(int n) {
    cnt = 0;
    sort(p, p + n);
    n = unique(p, p + n) - p;//去重

    for (int i = 0; i < n; i++) {
        while (cnt > 1 && dcmp(Cross(v[cnt - 1] - v[cnt - 2], p[i] - v[cnt - 2])) <= 0) cnt--;
        v[cnt++] = p[i];
    }
    int k = cnt;
    for (int i = n - 2; ~i; --i) {
        while (cnt > k && dcmp(Cross(v[cnt - 1] - v[cnt - 2], p[i] - v[cnt - 2])) <= 0) cnt--;
        v[cnt++] = p[i];
    }
    if (n > 1)  cnt--;
}

db Solve() {
    if (n == 1) return 0;//特判
    db res = 1e18, X = 0, Y = 0;

    for (int i = 0; i < n; i++) {
        X += p[i].x;
        Y += p[i].y;
    }
    for (int i = 0; i < cnt; i++) {
        Point a = v[i], b = v[(i + 1) % cnt];
        db A = b.y - a.y, B = a.x - b.x, C = Cross(b, a);
        db calc = fabs((A * X + B * Y + C * n) / sqrt(A * A + B * B));
        if (dcmp(calc - res) < 0) {
            res = calc;
        }
    }

    return res / n;
}

int main() {
    scanf("%d", &T);
    for (int kase = 1; kase <= T; kase++) {
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%lf %lf", &p[i].x, &p[i].y);

        ConvexHull(n);//求凸包
        printf("Case #%d: %.3lf\n", kase, Solve());
    }
}

UVa 11168(凸包、直线一般式)

标签:clu   def   int()   pac   for   namespace   poi   iostream   int   

原文地址:https://www.cnblogs.com/AlphaWA/p/10961547.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!