题意:
给出一些点,求最小的覆盖这些点的矩形的面积。
题解:
枚举下边界(是一条边),然后暴力卡壳左右边界(点),再暴力上边界(点),更新答案。
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath> 7 8 #define N 2222 9 #define EPS 1e-7 10 #define INF 1e20 11 12 using namespace std; 13 14 struct PO 15 { 16 double x,y; 17 }p[N],stk[N],o; 18 19 int n,top; 20 int s[10]; 21 double ans; 22 23 inline int dc(double x) 24 { 25 if(x>EPS) return 1; 26 else if(x<-EPS) return -1; 27 return 0; 28 } 29 30 inline bool cmp(const PO &a,const PO &b) 31 { 32 if(dc(a.x-b.x)==0) return a.y<b.y; 33 return a.x<b.x; 34 } 35 36 inline PO operator +(PO a,PO b) 37 { 38 PO c; 39 c.x=a.x+b.x; 40 c.y=a.y+b.y; 41 return c; 42 } 43 44 inline PO operator -(PO a,PO b) 45 { 46 PO c; 47 c.x=a.x-b.x; 48 c.y=a.y-b.y; 49 return c; 50 } 51 52 inline double cross(PO &a,PO &b,PO &c) 53 { 54 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 55 } 56 57 inline double getangle(PO &a,PO &b,PO&c,PO &d) 58 { 59 PO t=c+(a-d); 60 return cross(b,a,t); 61 } 62 63 inline PO getfline(PO &a,PO &b,PO &c)//得到垂线 64 { 65 PO d=c-b,e; 66 e.x=a.x-d.y; 67 e.y=a.y+d.x; 68 return e; 69 } 70 71 inline double getdis(PO &a,PO &b) 72 { 73 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 74 } 75 76 inline double getdis_ps(PO &a,PO &b,PO &c) 77 { 78 return fabs(cross(a,b,c))/getdis(b,c); 79 } 80 81 inline void getside() 82 { 83 for(int i=0;i<4;i++) s[i]=0; 84 for(int i=1;i<top;i++) 85 { 86 if(dc(stk[i].y-stk[s[0]].y)<0) s[0]=i; 87 if(dc(stk[i].x-stk[s[1]].x)<0) s[1]=i; 88 if(dc(stk[i].y-stk[s[2]].y)>0) s[2]=i; 89 if(dc(stk[i].x-stk[s[3]].x)>0) s[3]=i; 90 } 91 // 0 == ymin, 1 == xmin, 2 == ymax ,3 == xmax; 92 } 93 94 inline void rotating_calipers() 95 { 96 getside(); 97 int tmp=s[0]; 98 ans=INF; 99 do 100 {//枚举下边界(直线) 101 PO t=getfline(stk[s[0]],stk[s[0]],stk[(s[0]+1)%top]); 102 while(dc(getangle(t,stk[s[0]],stk[s[1]],stk[(s[1]+1)%top]))<0) s[1]=(s[1]+1)%top;//卡右边界 103 while(dc(getangle(stk[s[0]],t,stk[s[3]],stk[(s[3]+1)%top]))<0) s[3]=(s[3]+1)%top;//卡做边界 104 while(dc(getdis_ps(stk[(s[2]+1)%top],stk[s[0]],stk[(s[0]+1)%top])- 105 getdis_ps(stk[s[2]],stk[s[0]],stk[(s[0]+1)%top]))>0) s[2]=(s[2]+1)%top;//卡上边界 106 double a=getdis_ps(stk[s[2]],stk[s[0]],stk[(s[0]+1)%top]); 107 t=getfline(stk[s[3]],stk[s[0]],stk[(s[0]+1)%top]); 108 double b=getdis_ps(stk[s[1]],stk[s[3]],t); 109 ans=min(ans,a*b); 110 s[0]=(s[0]+1)%top; 111 }while(s[0]!=tmp); 112 } 113 114 inline void graham() 115 { 116 sort(p+1,p+1+n,cmp); 117 top=-1; 118 stk[++top]=p[1]; stk[++top]=p[2]; 119 for(int i=3;i<=n;i++) 120 { 121 while(top>=1&&dc(cross(stk[top-1],stk[top],p[i]))<=0) top--; 122 stk[++top]=p[i]; 123 } 124 int tmp=top; 125 for(int i=n-1;i>=1;i--) 126 { 127 while(top>=tmp+1&&dc(cross(stk[top-1],stk[top],p[i]))<=0) top--; 128 stk[++top]=p[i]; 129 } 130 } 131 132 inline void read() 133 { 134 for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); 135 } 136 137 inline void go() 138 { 139 if(n<=2) ans=0.0; 140 else graham(),rotating_calipers(); 141 printf("%.4lf\n",ans); 142 } 143 144 int main() 145 { 146 while(~scanf("%d",&n)&&n) read(),go(); 147 return 0; 148 }
这题傻X了,凸包写错了。。查了好久,都改得和题解一样了。。。~~~~(>_<)~~~~
一下自己yy的。
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <cmath> 7 8 #define N 2020 9 #define EPS 1e-7 10 11 using namespace std; 12 13 struct PO 14 { 15 double x,y; 16 inline void prt() {printf("%lf %lf\n",x,y);} 17 }p[N],stk[N],res[N],o; 18 19 int n,tot; 20 21 inline void read() 22 { 23 for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); 24 } 25 26 inline int dc(double x) 27 { 28 if(x>EPS) return 1; 29 else if(x<-EPS) return -1; 30 return 0; 31 } 32 33 inline bool cmp(const PO &a,const PO &b) 34 { 35 if(dc(a.x-b.x)==0) return a.y<b.y; 36 return a.x<b.x; 37 } 38 39 inline PO operator +(PO a,PO b) 40 { 41 a.x+=b.x; a.y+=b.y; 42 return a; 43 } 44 45 inline PO operator -(PO a,PO b) 46 { 47 a.x-=b.x; a.y-=b.y; 48 return a; 49 } 50 51 inline double cross(PO &a,PO &b,PO &c) 52 { 53 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 54 } 55 56 inline double dot(PO &a,PO &b,PO &c) 57 { 58 return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); 59 } 60 61 inline double getdis(PO &a,PO &b) 62 { 63 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 64 } 65 66 inline void graham() 67 { 68 sort(p+1,p+1+n,cmp); 69 tot=-1; int top=0; 70 for(int i=1;i<=n;i++) 71 { 72 while(top>=2&&dc(cross(stk[top-1],stk[top],p[i]))<=0) top--; 73 stk[++top]=p[i]; 74 } 75 for(int i=1;i<=top;i++) res[++tot]=stk[i]; 76 top=0; 77 for(int i=n;i>=1;i--) 78 { 79 while(top>=2&&dc(cross(stk[top-1],stk[top],p[i]))<=0) top--; 80 stk[++top]=p[i]; 81 } 82 for(int i=2;i<=top;i++) res[++tot]=stk[i]; 83 } 84 85 inline int getangle_dot(PO &a,PO &b,PO &c,PO &d) 86 { 87 PO e=d-(c-a); 88 return dc(dot(a,b,e)); 89 } 90 91 inline double getangle_cross(PO &a,PO &b,PO &c,PO &d) 92 { 93 PO e=d-(c-a); 94 return dc(cross(a,b,e)); 95 } 96 97 inline double getlen(PO &a) 98 { 99 return sqrt(a.x*a.x+a.y*a.y); 100 } 101 102 inline double getty(PO &a,PO &b) 103 { 104 return dot(o,a,b)/getlen(b); 105 } 106 107 inline void rotating_calipers() 108 { 109 double ans=1e20; 110 PO sa,sb; 111 for(int i=0;i<tot;i++) 112 { 113 int rt=(i+1)%tot; 114 while(getangle_dot(res[i],res[(i+1)%tot],res[rt],res[(rt+1)%tot])>0) rt=(rt+1)%tot; 115 int lt=i; 116 while(getangle_dot(res[i],res[(i+1)%tot],res[(lt-1+tot)%tot],res[lt])>0) lt=(lt-1+tot)%tot; 117 int usp=(i+1)%tot; 118 while(getangle_cross(res[i],res[i+1],res[usp],res[(usp+1)%tot])>0) usp=(usp+1)%tot; 119 double h=fabs(cross(res[i],res[i+1],res[usp]))/getdis(res[i],res[i+1]); 120 sa=res[rt]-res[lt]; sb=res[i+1]-res[i]; 121 ans=min(ans,fabs(h*getty(sa,sb))); 122 } 123 printf("%.4lf\n",ans); 124 } 125 126 inline void go() 127 { 128 graham(); 129 if(tot<=2) printf("0.0000\n"); 130 else if(tot==3) printf("%.4lf\n",fabs(cross(res[0],res[1],res[2]))); 131 else rotating_calipers(); 132 } 133 134 int main() 135 { 136 while(scanf("%d",&n),n)read(),go(); 137 return 0; 138 }