题目描述:
代码如下:
1 #include <algorithm> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <cstring> 6 #include <iostream> 7 #define INF 0x7fffffff 8 using namespace std; 9 10 typedef long long LL; 11 const int N = 1000 + 10; 12 const double PI = acos(-1.0); 13 const double esp = 1e-10; 14 15 int dcmp(double x) {if(fabs(x) < esp) return 0; else return x<0?-1:1;} 16 17 struct Point 18 { 19 double x,y; 20 Point(double x=0,double y=0):x(x),y(y){ } 21 }; 22 23 typedef Point Vector; 24 25 Vector operator + (Vector A, Vector B) {return Vector(A.x+B.x, A.y+B.y);} 26 Vector operator - (Vector A, Vector B) {return Vector(A.x-B.x, A.y-B.y);} 27 Vector operator * (Vector A, double p) {return Vector(A.x*p, A.y*p);} 28 Vector operator / (Vector A, double p) {return Vector(A.x/p, A.y/p);} 29 bool operator < (const Point& a, const Point& b){ return a.x<b.x || (a.x==b.x && a.y<b.y);} 30 bool operator == (const Point& a, const Point& b){return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;} 31 32 double Dot(Vector A, Vector B){ return A.x*B.x+A.y*B.y; } 33 double Length(Vector A){return sqrt(Dot(A, A));} //计算向量的模 34 double Angle(Vector A, Vector B) {return acos( Dot(A, B)/Length(A)/Length(B) );}//计算两向量的角度 35 36 double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x ;} //计算两向量的叉积 37 double Area2(Point A, Point B, Point C){return Cross(B-A, C-A); } //三点形成的两向量 38 39 double DistanceToLine(Point P, Point A, Point B) //计算以AB为底边的高 40 { 41 Vector v1 = B-A, v2 = P-A; 42 return fabs(Cross(v1, v2)) / Length(v1); 43 } 44 int ConvexHull(Point *p, int n, Point *ch) 45 { 46 sort(p,p+n); //排序各顶点 47 int m = 0; 48 for(int i=0;i<n;i++) //维护凸壳 49 { 50 while(m>1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; 51 ch[m++] = p[i]; //记录凸壳的顶点 52 } 53 int k = m; //记录凸壳顶点数 54 for(int i = n-2 ;i>=0;i--) //除去底边的两个顶点 55 { 56 while(m>k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; 57 ch[m++] = p[i]; 58 } 59 if(n > 1) m--; 60 return m; 61 } 62 63 int n; 64 Point P[N],ch[N]; 65 66 int main() 67 { 68 int C=1; 69 while(scanf("%d",&n)!=EOF && n) //输入多边形的边数 70 { 71 for(int i=0;i<n;i++) 72 { 73 scanf("%lf%lf",&P[i].x,&P[i].y);//记录各点的坐标 74 } 75 int m=ConvexHull(P,n,ch); //得到该多边形的凸壳顶点数 76 double ans = 1e20; //用于记录最小宽度 77 for(int i=1;i<=m;i++) //枚举凸壳的顶点 78 { 79 double max_dis = 0; //用于记录各底边的高 80 for(int j=0;j<m;j++) //确定底边后,查找其对应的高,并记录最大值 81 { 82 max_dis = max(max_dis, DistanceToLine(ch[j],ch[i%m],ch[i-1])); 83 } 84 ans = min(ans, max_dis);//最小宽度即为最大高度 85 } 86 ans = ceil(ans * 100) / 100.0; 87 88 printf("Case %d: %.2lf\n",C++, ans); 89 } 90 91 return 0; 92 }
解题思路:
该题使用了几何计算中的凸边算法(什么是凸边:https://blog.csdn.net/HouszChina/article/details/79251474)
首先对输入多边形的点进行凸壳维护,得到凸壳的点集
然后枚举底边,计算对应的高,并保留最大的高度(即题目要求的最小宽度)