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 }

 

 

你可能感兴趣的:(uva)