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

要点

  • 找凸包上的线很显然
  • 但每条线所有点都求一遍显然不可行,优化方法是:所有点都在一侧所以可以使用直线一般式的距离公式\(\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());
    }
}

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

时间: 2024-08-02 01:34:16

UVa 11168(凸包、直线一般式)的相关文章

UVa 11168 (凸包+点到直线距离) Airport

题意: 平面上有n个点,求一条直线使得所有点都在直线的同一侧.并求这些点到直线的距离之和的最小值. 分析: 只要直线不穿过凸包,就满足第一个条件.要使距离和最小,那直线一定在凸包的边上.所以求出凸包以后,枚举每个边求出所有点到直线的距离之和得到最小值. 点到直线距离公式为: 因为点都在直线同一侧,所以我们可以把加法“挪”到里面去,最后再求绝对值,所以可以预处理所有点的横坐标之和与纵坐标之和.当然常数C也要记得乘上n倍. 已知两点坐标求过该点直线的方程,这很好求不再赘述,考虑到直线没有斜率的情况,

UVa 11168 Airport , 凸包

题意: 给出平面上n个点,找一条直线,使得所有点在直线的同侧,且到直线的距离之平均值尽量小. 先求凸包 易知最优直线一定是凸包的某条边,然后利用点到直线距离公式进行计算. #include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<algorithm> #include<iostream> using namespace std; struc

简单几何(数学公式+凸包) UVA 11168 Airport

题目传送门 题意:找一条直线,使得其余的点都在直线的同一侧,而且使得到直线的平均距离最短. 分析:训练指南P274,先求凸包,如果每条边都算一边的话,是O (n ^ 2),然而根据公式知直线一般式为Ax + By + C = 0.点(x0, y0)到直线的距离为:fabs(Ax0+By0+C)/sqrt(A*A+B*B). 所以只要先求出x的和以及y的和,能在O (1)计算所有距离和. 两点式直线方程p1 (x1, y1),p2 (x2, y2)转换成一般式直线方程:A = y1 - y2, B

Airport UVA - 11168

Airport UVA - 11168 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 10010; 4 const int inf = 0x3f3f3f3f; 5 const int eps = 1e-12; 6 7 struct Point { 8 double x, y; 9 Point (double x = 0, double y = 0) : x(x), y(y) {} 10 }; 11 ty

编程求取直线一般式表达式,两直线交点

背景介绍 ??最近在水面无人艇(USV)模拟仿真中,用到了一些点和线的关系求解,本文主要讲述一下两点确认直线,点到直线距离,两条直线的交点等问题的解决方法,并给出python程序.部分内容非原创,文中给出链接,需要者可以参考. 两点确定直线 表达式定义 ??空间直线的表达式有多种,比如一般式Ax+By+C=0.点斜式y-y0=k(x-x0).截距式x/a+y/b=1.两点式:(y-y1)/(y1-y2)=(x-x1)/(x1-x2)等,它们具有彼此的约束条件,如下所示. ??由上可以看出来,一般

UVA 11168(凸包算法)

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34780 Problem 给N个点,画一条直线,所有点都在直线一侧(可以在直线上),且到达直线的平均距离最小(实际上就是总距离最小).输出平均距离,N有10000级别,点坐标挺大. Solution 首先,求一个凸包,枚举凸包点边,O(1)求出所有点到边的距离,维护最小值即可. 首先,为啥枚举凸包的边是对的? 其次,怎么O(1)求出,设直线返程为Ax+By+C=0, 点(x0

uva 11168

题意:有n个点,找一条直线,让所有点都在直线的同一侧(也可在直线上),且到直线的距离之和最小.输出距离和与点数的比值. 题解:所有点在直线同侧,也就是直线不能穿过凸包,那么凸包的边所在直线就是可能的解,点(x0,y0)到直线(Ax + By + C = 0)的距离 dis = |Ax0 + By0 + C| / sqrt(A^2 + B^2) 把凸包的每个边拿去计算,所有点到其的距离和,根据计算式,先把所有点的x坐标之和和y坐标之和计算出来减少时间复杂度. #include <cstdio>

UVA 10652 凸包问题

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 #include <iostream> 6 using namespace std; 7 8 const double eps = 1e-10; 9 const int N = 610; 10 int dcmp(double x) 11 { 12 if(abs(x) < e

poj1113 凸包

result=对所有点凸包周长+pi*2*L WA了一次,被Pi的精度坑了 以后注意Pi尽可能搞精确一点.Pi=3.14还是不够用 Code: 1 #include<vector> 2 #include<list> 3 #include<map> 4 #include<set> 5 #include<deque> 6 #include<queue> 7 #include<stack> 8 #include<bitse