hdu 5251 包围点集最小矩形 ***

题意:小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少。

求个凸包,矩形的边一定在凸包上,枚举边,求最大值,即为所求,多年不拍几何,直接套了个模板

以后还得练练

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 using namespace std;
  9 typedef double typev;
 10 const double eps = 1e-8;
 11 const int N = 4055;
 12 int sign(double d){
 13     return d < -eps ? -1 : (d > eps);
 14 }
 15 struct point{
 16     typev x, y;
 17     void in()
 18     {
 19         scanf("%lf%lf",&x,&y);
 20     }
 21     point operator-(point d){
 22         point dd;
 23         dd.x = this->x - d.x;
 24         dd.y = this->y - d.y;
 25         return dd;
 26     }
 27     point operator+(point d){
 28         point dd;
 29         dd.x = this->x + d.x;
 30         dd.y = this->y + d.y;
 31         return dd;
 32     }
 33     void read(){ scanf("%lf%lf", &x, &y); }
 34 }ps[N],pd[N];
 35 int n, cn;
 36 double dist(point d1, point d2){
 37     return sqrt(pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0));
 38 }
 39 double dist2(point d1, point d2){
 40     return pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0);
 41 }
 42 bool cmp(point d1, point d2){
 43     return d1.y < d2.y || (d1.y == d2.y && d1.x < d2.x);
 44 }
 45 //st1-->ed1叉乘st2-->ed2的值
 46 typev xmul(point st1, point ed1, point st2, point ed2){
 47     return (ed1.x - st1.x) * (ed2.y - st2.y) - (ed1.y - st1.y) * (ed2.x - st2.x);
 48 }
 49 typev dmul(point st1, point ed1, point st2, point ed2){
 50     return (ed1.x - st1.x) * (ed2.x - st2.x) + (ed1.y - st1.y) * (ed2.y - st2.y);
 51 }
 52 //多边形类
 53 struct poly{
 54     static const int N = 4005; //点数的最大值
 55     point ps[N+5]; //逆时针存储多边形的点,[0,pn-1]存储点
 56     int pn;  //点数
 57     poly() { pn = 0; }
 58     //加进一个点
 59     void push(point tp){
 60         ps[pn++] = tp;
 61     }
 62     //第k个位置
 63     int trim(int k){
 64         return (k+pn)%pn;
 65     }
 66     void clear(){ pn = 0; }
 67 };
 68 //返回含有n个点的点集ps的凸包
 69 poly graham(point* ps, int n){
 70     sort(ps, ps + n, cmp);
 71     poly ans;
 72     if(n <= 2){
 73         for(int i = 0; i < n; i++){
 74             ans.push(ps[i]);
 75         }
 76         return ans;
 77     }
 78     ans.push(ps[0]);
 79     ans.push(ps[1]);
 80     point* tps = ans.ps;
 81     int top = -1;
 82     tps[++top] = ps[0];
 83     tps[++top] = ps[1];
 84     for(int i = 2; i < n; i++){
 85         while(top > 0 && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--;
 86         tps[++top] = ps[i];
 87     }
 88     int tmp = top;  //注意要赋值给tmp!
 89     for(int i = n - 2; i >= 0; i--){
 90         while(top > tmp && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--;
 91         tps[++top] = ps[i];
 92     }
 93     ans.pn = top;
 94     return ans;
 95 }
 96 //求点p到st->ed的垂足,列参数方程
 97 point getRoot(point p, point st, point ed){
 98     point ans;
 99     double u=((ed.x-st.x)*(ed.x-st.x)+(ed.y-st.y)*(ed.y-st.y));
100     u = ((ed.x-st.x)*(ed.x-p.x)+(ed.y-st.y)*(ed.y-p.y))/u;
101     ans.x = u*st.x+(1-u)*ed.x;
102     ans.y = u*st.y+(1-u)*ed.y;
103     return ans;
104 }
105 //next为直线(st,ed)上的点,返回next沿(st,ed)右手垂直方向延伸l之后的点
106 point change(point st, point ed, point next, double l){
107     point dd;
108     dd.x = -(ed - st).y;
109     dd.y = (ed - st).x;
110     double len = sqrt(dd.x * dd.x + dd.y * dd.y);
111     dd.x /= len, dd.y /= len;
112     dd.x *= l, dd.y *= l;
113     dd = dd + next;
114     return dd;
115 }
116 //求含n个点的点集ps的最小面积矩形,并把结果放在ds(ds为一个长度是4的数组即可,ds中的点是逆时针的)中,并返回这个最小面积。
117 double getMinAreaRect(point* ps, int n, point* ds){
118     int cn, i;
119     double ans;
120     point* con;
121     poly tpoly = graham(ps, n);
122     con = tpoly.ps;
123     cn = tpoly.pn;
124     if(cn <= 2){
125         ds[0] = con[0]; ds[1] = con[1];
126         ds[2] = con[1]; ds[3] = con[0];
127         ans=0;
128     }else{
129         int  l, r, u;
130         double tmp, len;
131         con[cn] = con[0];
132         ans = 1e40;
133         l = i = 0;
134         while(dmul(con[i], con[i+1], con[i], con[l])
135             >= dmul(con[i], con[i+1], con[i], con[(l-1+cn)%cn])){
136                 l = (l-1+cn)%cn;
137         }
138         for(r=u=i = 0; i < cn; i++){
139             while(xmul(con[i], con[i+1], con[i], con[u])
140                 <= xmul(con[i], con[i+1], con[i], con[(u+1)%cn])){
141                     u = (u+1)%cn;
142             }
143             while(dmul(con[i], con[i+1], con[i], con[r])
144                 <= dmul(con[i], con[i+1], con[i], con[(r+1)%cn])){
145                     r = (r+1)%cn;
146             }
147             while(dmul(con[i], con[i+1], con[i], con[l])
148                 >= dmul(con[i], con[i+1], con[i], con[(l+1)%cn])){
149                     l = (l+1)%cn;
150             }
151             tmp = dmul(con[i], con[i+1], con[i], con[r]) - dmul(con[i], con[i+1], con[i], con[l]);
152             tmp *= xmul(con[i], con[i+1], con[i], con[u]);
153             tmp /= dist2(con[i], con[i+1]);
154             len = xmul(con[i], con[i+1], con[i], con[u])/dist(con[i], con[i+1]);
155             if(sign(tmp - ans) < 0){
156                 ans = tmp;
157                 ds[0] = getRoot(con[l], con[i], con[i+1]);
158                 ds[1] = getRoot(con[r], con[i+1], con[i]);
159                 ds[2] = change(con[i], con[i+1], ds[1], len);
160                 ds[3] = change(con[i], con[i+1], ds[0], len);
161             }
162         }
163     }
164     return ans+eps;
165 }
166 int main()
167 {
168     int i,j,k;
169     #ifndef ONLINE_JUDGE
170     freopen("1.in","r",stdin);
171     #endif
172     int tt;
173     scanf("%d",&tt);
174     int ca=1;
175     while(tt--)
176     {
177         printf("Case #%d:\n",ca++);
178         scanf("%d",&n);
179         for(i=0;i<4*n;i++)
180         {
181             ps[i].in();
182         }
183         double q=getMinAreaRect(ps,4*n,pd);
184         printf("%d\n",int(q+0.5));
185     }
186 }
View Code

 

posted @ 2015-05-30 22:24  miao_a_miao  阅读(861)  评论(0编辑  收藏  举报