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

百般思念 提交于 2020-03-27 09:56:01

题意:

平面上有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 }
代码君

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!