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

题意:

平面上有n个点,求一条直线使得所有点都在直线的同一侧。并求这些点到直线的距离之和的最小值。

分析:

只要直线不穿过凸包,就满足第一个条件。要使距离和最小,那直线一定在凸包的边上。所以求出凸包以后,枚举每个边求出所有点到直线的距离之和得到最小值。

点到直线距离公式为:

因为点都在直线同一侧,所以我们可以把加法“挪”到里面去,最后再求绝对值,所以可以预处理所有点的横坐标之和与纵坐标之和。当然常数C也要记得乘上n倍。

已知两点坐标求过该点直线的方程,这很好求不再赘述,考虑到直线没有斜率的情况,最终要把表达式中的分母乘过去。

 

  1 //#define LOCAL

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <cmath>

  6 #include <vector>

  7 using namespace std;

  8 

  9 struct Point

 10 {

 11     double x, y;

 12     Point(double x=0, double y=0):x(x), y(y) {}

 13 };

 14 typedef Point Vector;

 15 Point operator + (Point A, Point B)

 16 {

 17     return Point(A.x+B.x, A.y+B.y);

 18 }

 19 Point operator - (Point A, Point B)

 20 {

 21     return Point(A.x-B.x, A.y-B.y);

 22 }

 23 bool operator < (const Point& A, const Point& B)

 24 {

 25     return A.x < B.x || (A.x == B.x && A.y < B.y);

 26 }

 27 bool operator == (const Point& A, const Point& B)

 28 {

 29     return A.x == B.x && A.y == B.y;

 30 }

 31 double Cross(Vector A, Vector B)

 32 {

 33     return A.x*B.y - A.y*B.x;

 34 }

 35 

 36 vector<Point> ConvexHull(vector<Point> p) {

 37   // 预处理,删除重复点

 38   sort(p.begin(), p.end());

 39   p.erase(unique(p.begin(), p.end()), p.end());

 40 

 41   int n = p.size();

 42   int m = 0;

 43   vector<Point> ch(n+1);

 44   for(int i = 0; i < n; i++) {

 45     while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;

 46     ch[m++] = p[i];

 47   }

 48   int k = m;

 49   for(int i = n-2; i >= 0; i--) {

 50     while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;

 51     ch[m++] = p[i];

 52   }

 53   if(n > 1) m--;

 54   //for(int i = 0; i < m; ++i) printf("%lf %lf\n", ch[i].x, ch[i].y);

 55   ch.resize(m);

 56   return ch;

 57 }

 58 

 59 double sumx, sumy;

 60 

 61 double Dist(Point a, Point b, int m)

 62 {

 63     double A = a.y-b.y, B = b.x-a.x, C = a.x*b.y - b.x*a.y;

 64     //printf("%lf %lf", fabs(A*sumx+B*sumy+C), sqrt(A*A+B*B));

 65     return (fabs(A*sumx+B*sumy+C*m) / sqrt(A*A+B*B));

 66 }

 67 

 68 int main(void)

 69 {

 70     #ifdef LOCAL

 71         freopen("11168in.txt", "r", stdin);

 72     #endif

 73     

 74     int T;

 75     scanf("%d", &T);

 76     for(int kase = 1; kase <= T; ++kase)

 77     {

 78         int n;

 79         vector<Point> p;

 80         sumx = 0.0, sumy = 0.0;

 81         scanf("%d", &n);

 82         for(int i = 0; i < n; ++i)

 83         {

 84             double x, y;

 85             scanf("%lf%lf", &x, &y);

 86             p.push_back(Point(x, y));

 87             sumx += x;    sumy += y;

 88         }

 89         vector<Point> ch = ConvexHull(p);

 90         int m = ch.size();

 91         //for(int i = 0; i < m; ++i)    printf("%lf %lf\n", ch[i].x, ch[i].y);

 92         if(m <= 2)

 93         {

 94             printf("Case #%d: 0.000\n", kase);

 95             continue;

 96         }

 97         

 98         double ans = 1e10;

 99         for(int i = 0; i < m; ++i)

100             ans = min(ans, Dist(ch[i], ch[(i+1)%m], n));

101         printf("Case #%d: %.3lf\n", kase, ans/n);

102     }

103 }
代码君

 

你可能感兴趣的:(port)