UVA 10173 旋转卡壳

题意:
给出一些点,求最小的覆盖这些点的矩形的面积。

题解:

枚举下边界(是一条边),然后暴力卡壳左右边界(点),再暴力上边界(点),更新答案。

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 }
原文地址:https://www.cnblogs.com/proverbs/p/2932721.html