uva 11168

uva 11168

题意:给出平面上的n个点,求一条直线,使得所有点在该直线的同一侧且所有点到该直线的距离和最小,输出该距离和。

思路:要使所有点在该直线的同一侧,明显是直接利用凸包的边更优。所以枚举凸包的没条边,然后求距离和。直线一般式为Ax + By + C = 0.点(x0, y0)到直线的距离为 fabs(Ax0+By0+C)/sqrt(A*A+B*B).由于所有点在直线的同一侧,那么对于所有点,他们的(Ax0+By0+C)符号相同,显然可以累加出sumX和sumY,然后统一求和。

水。。。。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 #define up(i,x,y) for(i=x;i<=y;i++)
 12 #define w(a) while(a)
 13 using namespace std;
 14 const double inf=0x3f3f3f3f;
 15 const int N = 4010;
 16 const double eps = 5*1e-13;
 17 const double PI = acos(-1.0);
 18 
 19 double torad(double deg)
 20 {
 21     return deg/180 * PI;
 22 }
 23 
 24 struct Point
 25 {
 26     double x, y;
 27     Point(double x=0, double y=0):x(x),y(y) { }
 28 };
 29 
 30 typedef Point Vector;
 31 
 32 Vector operator + (const Vector& A, const Vector& B)
 33 {
 34     return Vector(A.x+B.x, A.y+B.y);
 35 }
 36 Vector operator - (const Point& A, const Point& B)
 37 {
 38     return Vector(A.x-B.x, A.y-B.y);
 39 }
 40 double Cross(const Vector& A, const Vector& B)
 41 {
 42     return A.x*B.y - A.y*B.x;
 43 }
 44 
 45 Vector Rotate(const Vector& A, double rad)
 46 {
 47     return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
 48 }
 49 
 50 bool operator < (const Point& p1, const Point& p2)
 51 {
 52     return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
 53 }
 54 
 55 bool operator == (const Point& p1, const Point& p2)
 56 {
 57     return p1.x == p2.x && p1.y == p2.y;
 58 }
 59 
 60 // 点集凸包
 61 // 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
 62 // 如果不介意点集被修改,可以改成传递引用
 63 vector<Point> ConvexHull(vector<Point> p)
 64 {
 65     // 预处理,删除重复点
 66     sort(p.begin(), p.end());
 67     p.erase(unique(p.begin(), p.end()), p.end());
 68 
 69     int n = p.size();
 70     int m = 0;
 71     vector<Point> ch(n+1);
 72     for(int i = 0; i < n; i++)
 73     {
 74         while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
 75         ch[m++] = p[i];
 76     }
 77     int k = m;
 78     for(int i = n-2; i >= 0; i--)
 79     {
 80         while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
 81         ch[m++] = p[i];
 82     }
 83     if(n > 1) m--;
 84     ch.resize(m);
 85     return ch;
 86 }
 87 
 88 // 过两点p1, p2的直线一般方程ax+by+c=0
 89 // (x2-x1)(y-y1) = (y2-y1)(x-x1)
 90 void getLineGeneralEquation(const Point& p1, const Point& p2, double& a, double& b, double &c) {
 91   a = p2.y-p1.y;
 92   b = p1.x-p2.x;
 93   c = -a*p1.x - b*p1.y;
 94 }
 95 
 96 int main()
 97 {
 98     int t,n;
 99     double x,y;
100     double sumx,sumy;
101     double ans;
102     int cas=1;
103     scanf("%d",&t);
104     while(t--)
105     {
106         scanf("%d",&n);
107         vector<Point>p;
108         sumx=0;sumy=0;
109         for(int i=0;i<n;i++)
110         {
111             scanf("%lf%lf",&x,&y);
112             sumx+=x;sumy+=y;
113             p.push_back(Point(x,y));
114         }
115         vector<Point>ch=ConvexHull(p);
116         ans=inf;
117         int edge=ch.size();
118         if(edge<=2)
119         {
120             ans=0;
121         }
122         else
123         {
124             for(int i=0;i<edge;i++)
125             {
126                 double a,b,c;
127                 getLineGeneralEquation(ch[i],ch[(i+1)%edge],a,b,c);
128                 ans=min(ans,fabs(sumx*a+sumy*b+n*c)/sqrt(a*a+b*b));
129             }
130         }
131         printf("Case #%d: %.3f
",cas++,ans/n);
132     }
133     return 0;
134 }
View Code