UVA 11168 Airport(凸包)

 

UVA 11168 Airport(凸包)

分类: 计算几何   245人阅读  评论(1)  收藏  举报

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

要使所有点在该直线的同一侧,明显是直接利用凸包的边更优。所以枚举凸包的没条边,然后求距离和。直线一般式为Ax + By + C = 0.点(x0, y0)到直线的距离为

fabs(Ax0+By0+C)/sqrt(A*A+B*B).由于所有点在直线的同一侧,那么对于所有点,他们的(Ax0+By0+C)符号相同,显然可以累加出sumX和sumY,然后统一求和。

[cpp]  view plain copy
  1. #include<algorithm>  
  2. #include<iostream>  
  3. #include<cstring>  
  4. #include<cstdlib>  
  5. #include<fstream>  
  6. #include<sstream>  
  7. #include<bitset>  
  8. #include<vector>  
  9. #include<string>  
  10. #include<cstdio>  
  11. #include<cmath>  
  12. #include<stack>  
  13. #include<queue>  
  14. #include<stack>  
  15. #include<map>  
  16. #include<set>  
  17. #define FF(i, a, b) for(int i=a; i<b; i++)  
  18. #define FD(i, a, b) for(int i=a; i>=b; i--)  
  19. #define REP(i, n) for(int i=0; i<n; i++)  
  20. #define CLR(a, b) memset(a, b, sizeof(a))  
  21. #define debug puts("**debug**")  
  22. #define LL long long  
  23. #define PB push_back  
  24. #define eps 1e-10  
  25. using namespace std;  
  26.   
  27. struct Point  
  28. {  
  29.     double x, y;  
  30.     Point (double x=0, double y=0):x(x), y(y) {}  
  31. };  
  32. typedef Point Vector;  
  33.   
  34. Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }  
  35. Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }  
  36. Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }  
  37. Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }  
  38.   
  39. bool operator < (const Point& a, const Point& b)  
  40. {  
  41.     return a.x < b.x || (a.x == b.x && a.y < b.y);  
  42. }  
  43.   
  44. int dcmp(double x)  
  45. {  
  46.     if(fabs(x) < eps) return 0;  
  47.     return x < 0 ? -1 : 1;  
  48. }  
  49.   
  50. bool operator == (const Point& a, const Point& b)  
  51. {  
  52.     return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;  
  53. }  
  54.   
  55. double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }  
  56. double Length(Vector A) { return sqrt(Dot(A, A)); }  
  57. double Angel(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }  
  58.   
  59. double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }  
  60. double Area2(Vector A, Vector B, Vector C) { return Cross(B-A, C-A); }  
  61.   
  62.   
  63. //向量逆时针旋转  
  64. Vector Rotate(Vector A, double rad)  
  65. {  
  66.     return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));  
  67. }  
  68.   
  69. //求直线p+tv和q+tw的交点 Cross(v, w) == 0无交点  
  70. Point GetLineIntersection(Point p, Vector v, Point q, Vector w)  
  71. {  
  72.     Vector u = p-q;  
  73.     double t = Cross(w, u) / Cross(v, w);  
  74.     return p + v*t;  
  75. }  
  76.   
  77.   
  78. //点p到直线ab的距离  
  79. double DistanceToLine(Point p, Point a, Point b)  
  80. {  
  81.     Vector v1 = b - a, v2 = p - a;  
  82.     return fabs(Cross(v1, v2)) / Length(v1);//如果不带fabs 得到的是有向距离  
  83. }  
  84.   
  85. //点p到线段ab的距离  
  86. double DistanceToSegment(Point p, Point a, Point b)  
  87. {  
  88.     if(a == b) return Length(p-a);  
  89.     Vector v1 = b-a, v2 = p-a, v3 = p-b;  
  90.     if(dcmp(Dot(v1, v2) < 0)) return Length(v2);  
  91.     else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);  
  92.     else return fabs(Cross(v1, v2)) / Length(v1);  
  93. }  
  94.   
  95. //点p在直线ab上的投影  
  96. Point GetLineProjection(Point p, Point a, Point b)  
  97. {  
  98.     Vector v = b-a;  
  99.     return a + v*(Dot(v, p-a) / Dot(v, v));  
  100. }  
  101.   
  102. //点段相交判定  
  103. bool SegmentItersection(Point a1, Point a2, Point b1, Point b2)  
  104. {  
  105.     double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1),  
  106.     c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);  
  107.     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;  
  108. }  
  109.   
  110. //点在线段上  
  111. bool OnSegment(Point p, Point a1, Point a2)  
  112. {  
  113.     return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;  
  114. }  
  115.   
  116. //多变形面积  
  117. double PolygonArea(Point* p, int n)  
  118. {  
  119.     double ret = 0;  
  120.     FF(i, 1, n-1) ret += Cross(p[i]-p[0], p[i+1]-p[0]);  
  121.     return ret/2;  
  122. }  
  123.   
  124. Point read_point()  
  125. {  
  126.     Point a;  
  127.     scanf("%lf%lf", &a.x, &a.y);  
  128.     return a;  
  129. }  
  130.   
  131. double torad(double d)//角度转弧度  
  132. {  
  133.     return d/180 *acos(-1);  
  134. }  
  135.   
  136. int ConvexHull(Point *p, int n, Point* ch)//凸包  
  137. {  
  138.     sort(p, p+n);  
  139.     int m = 0;  
  140.     REP(i, n)  
  141.     {  
  142.         while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;  
  143.         ch[m++] = p[i];  
  144.     }  
  145.     int k = m;  
  146.     FD(i, n-2, 0)  
  147.     {  
  148.         while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;  
  149.         ch[m++] = p[i];  
  150.     }  
  151.     if(n > 1) m--;  
  152.     return m;  
  153. }  
  154.   
  155. void getLineABC(Point A, Point B, double& a, double& b, double& c)//直线两点式转一般式  
  156. {  
  157.     a = A.y-B.y, b = B.x-A.x, c = A.x*B.y-A.y*B.x;  
  158. }  
  159.   
  160. const int maxn = 10001;  
  161. int n, T;  
  162. Point p[maxn], ch[maxn];  
  163.   
  164. int main()  
  165. {  
  166.     scanf("%d", &T);  
  167.     FF(kase, 1, T+1)  
  168.     {  
  169.         scanf("%d", &n);  
  170.         double X = 0, Y = 0, ans = 1e10;  
  171.         REP(i, n) p[i] = read_point(), X += p[i].x, Y += p[i].y;  
  172.         int m = ConvexHull(p, n, ch);  
  173.         ch[m] = ch[0];  
  174.         REP(i, m)  
  175.         {  
  176.             double a, b, c;  
  177.             getLineABC(ch[i], ch[i+1], a, b, c);  
  178.             ans = min(ans, fabs(a*X+b*Y+c*n)/(sqrt(a*a+b*b)));  
  179.         }  
  180.         printf("Case #%d: %.3f\n", kase, n > 2 ? ans/n : 0);  
  181.     }  
  182.     return 0;  
  183. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值