题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点
这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性
所以可以利用旋转卡壳的思想找到这样的三个点
以每一条边作为基础,循环n次得到n个这样的矩形,找到其中面积最小的即可
然后自己画画图,作出矩形对应的两条边的单位向量,那么这四个点就非常好求了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 #define N 50010 8 #define eps 1e-9 9 const double PI = acos(-1.0); 10 int n , top; 11 12 int dcmp(double x) 13 { 14 if(fabs(x)<eps) return 0; 15 return x<0?-1:1; 16 } 17 18 struct Point{ 19 double x , y; 20 Point(double x=0 , double y=0):x(x),y(y){} 21 void input(){scanf("%lf%lf" , &x , &y);} 22 void output(){printf("%.5f %.5f\n" , x , y);} 23 bool operator<(const Point &m)const{ 24 return x<m.x||(x==m.x&&y<m.y); 25 } 26 }po[N] , rec[N] , p[4]; 27 28 typedef Point Vector; 29 30 Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);} 31 Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);} 32 Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);} 33 Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);} 34 double operator*(Vector a , Vector b){return a.x*b.y-a.y*b.x;} 35 36 double Dot(Vector a , Vector b){return a.x*b.x+a.y*b.y;} 37 double Len(Vector a){return sqrt(Dot(a,a));} 38 int Polxy() 39 { 40 sort(po , po+n); 41 rec[0]=po[0] , rec[1]=po[1]; 42 top=2; 43 for(int i=2 ; i<n ; i++){ 44 while(top>=2&&(rec[top-1]-rec[top-2])*(po[i]-rec[top-2])<=0) 45 top--; 46 rec[top++] = po[i]; 47 } 48 int tmp=top; 49 for(int i=n-2 ; i>=0 ; i--){ 50 while(top>=tmp&&(rec[top-1]-rec[top-2])*(po[i]-rec[top-2])<=0) 51 top--; 52 rec[top++] = po[i]; 53 } 54 top--; 55 return top; 56 } 57 58 Vector Normal(Vector a) 59 { 60 double l = Len(a); 61 return Vector(-a.y/l , a.x/l); 62 } 63 64 double calCalip() 65 { 66 // for(int i=0 ; i<top ; i++) rec[i].output(); 67 Point ch[2]; 68 ch[0] = rec[0] , ch[1] = rec[1]; 69 int i1=0 , i2=0 , i3=0; 70 double maxn = 1e18; 71 ch[0] = rec[0] , ch[1] = rec[1]; 72 while(dcmp(fabs((rec[(i1+1)%top]-ch[0])*(ch[1]-ch[0]))-fabs((rec[i1]-ch[0])*(ch[1]-ch[0])))>=0) i1=(i1+1)%top; 73 while(dcmp(Dot(rec[(i2+1)%top]-ch[0] , ch[1]-ch[0])-Dot(rec[i2]-ch[0] , ch[1]-ch[0]))>=0) i2=(i2+1)%top; 74 while(dcmp(Dot(rec[(i3-1+top)%top]-ch[1] , ch[0]-ch[1])-Dot(rec[i3]-ch[1] , ch[0]-ch[1]))>=0) i3=(i3-1+top)%top; 75 for(int i=0 ; i<top ; i++){ 76 ch[0] = rec[i] , ch[1] = rec[(i+1)%top]; 77 while(dcmp(fabs((rec[(i1+1)%top]-ch[0])*(ch[1]-ch[0]))-fabs((rec[i1]-ch[0])*(ch[1]-ch[0])))>=0) i1=(i1+1)%top; 78 while(dcmp(Dot(rec[(i2+1)%top]-ch[0] , ch[1]-ch[0])-Dot(rec[i2]-ch[0] , ch[1]-ch[0]))>=0) i2=(i2+1)%top; 79 while(dcmp(Dot(rec[(i3+1)%top]-ch[1] , ch[0]-ch[1])-Dot(rec[i3]-ch[1] , ch[0]-ch[1]))>=0) i3=(i3+1)%top; 80 double l = Len(ch[1]-ch[0]); 81 double h = fabs((rec[i1]-ch[0])*(ch[1]-ch[0]))/l; 82 double len1 = Dot(rec[i2]-ch[1] , ch[1]-ch[0])/l; //右侧长度 83 double len2 = Dot(rec[i3]-ch[0] , ch[0]-ch[1])/l; //左侧长度 84 double suml = l+len1+len2; 85 // cout<<i<<" "<<l<<" "<<h<<" "<<len1<<" "<<len2<<" "<<suml*h<<endl; 86 if(dcmp(suml*h-maxn)<0){ 87 Vector unit1 = (ch[1]-ch[0])/l; 88 Vector unit2 = Normal(unit1); 89 maxn = suml*h; 90 p[0] = ch[1]+unit1*len1; 91 p[1] = p[0]+unit2*h; 92 p[2] = p[1]-unit1*suml; 93 p[3] = p[2]-unit2*h; 94 } 95 } 96 return maxn; 97 } 98 99 int main() 100 { 101 // freopen("in.txt" , "r" , stdin); 102 while(scanf("%d" , &n)!=EOF) 103 { 104 for(int i=0 ; i<n ; i++) po[i].input(); 105 Polxy(); 106 double ret = calCalip(); 107 printf("%.5f\n" , ret); 108 int st = 0; 109 for(int i=1 ; i<4 ; i++){ 110 if(p[i].y<p[st].y || (p[i].y==p[st].y&&p[i].x<p[st].x)) st = i; 111 } 112 for(int i=0;i<4;i++){ 113 p[st].output(); 114 st = (st+1)%4; 115 } 116 } 117 return 0; 118 }
时间: 2024-10-05 15:05:23