UVa 11168(凸包直线一般式)
Posted alphawa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 11168(凸包直线一般式)相关的知识,希望对你有一定的参考价值。
要点
- 找凸包上的线很显然
- 但每条线所有点都求一遍显然不可行,优化方法是:所有点都在一侧所以可以使用直线一般式的距离公式\(\frac|A* \sumx+B* \sumy+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(凸包直线一般式)的主要内容,如果未能解决你的问题,请参考以下文章
UVA10256 The Great Divide(凸包相交)