zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", ch[i].x, ch[i].y);
     92         if(m <= 2)
     93         {
     94             printf("Case #%d: 0.000
    ", 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
    ", kase, ans/n);
    102     }
    103 }
    代码君
  • 相关阅读:
    软件的一般实现过程
    前端开发所需技能及理解
    前端开发所需技能
    JavaScriptlet和const的使用
    [NOI2013] 向量内积
    [省选联考 2021 A/B 卷] 滚榜
    [提高组集训2021] 模拟赛2
    [省选联考 2021 A 卷] 矩阵游戏
    [省选联考 2021 A/B 卷] 图函数
    [APIO2020] 交换城市
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4036163.html
Copyright © 2011-2022 走看看