【BZOJ 1185】 凸包+旋转卡壳

Description

【分析】

  打计算几何真的可以哭出来。。。

  跟那个求线段最远点差不多,这题弄三个东西转一转,一个表示左端最远点,一个表示右端最远点,一个表示上面最远点。

  左右两边的最远点用点积判断,上方最远点用差积判断。

  【向量是最好的解决平面几何问题的,不要画图!!!哭!!!

  输出那里,用的是向量加减法,乘一个比例系数,然后还用到了垂直单位向量。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 using namespace std;
  8 #define Maxn 50010
  9
 10 const double eps=0.0000001;
 11 const double INF=999999999;
 12
 13 struct P
 14 {
 15     double x,y;
 16 }a[Maxn],t[Maxn];
 17 int len,n;
 18
 19 P operator - (P x,P y)
 20 {
 21     P tt;
 22     tt.x=x.x-y.x;
 23     tt.y=x.y-y.y;
 24     return tt;
 25 }
 26
 27 P operator * (P x,double y)
 28 {
 29     P tt;
 30     tt.x=x.x*y;
 31     tt.y=x.y*y;
 32     return tt;
 33 }
 34
 35 P operator + (P x,P y)
 36 {
 37     P tt;
 38     tt.x=x.x+y.x;
 39     tt.y=x.y+y.y;
 40     return tt;
 41 }
 42
 43 double myabs(double x) {return x>0?x:-x;}
 44
 45 int fbs(double x)
 46 {
 47     if(myabs(x)<=eps) return 0;
 48     return x<0?-1:1;
 49 }
 50
 51 double Dot(P x,P y) {return x.x*y.x+x.y*y.y;}
 52 double Cross(P x,P y) {return x.x*y.y-x.y*y.x;}
 53 bool cmp(P x,P y) {return fbs(x.x-y.x)==0?(x.y<y.y):(x.x<y.x);}
 54
 55 void chull()
 56 {
 57     sort(a+1,a+1+n,cmp);
 58     len=0;
 59     for(int i=1;i<=n;i++)
 60     {
 61         while(len>1&&Cross(t[len]-t[len-1],a[i]-t[len])<=0) len--;
 62         t[++len]=a[i];
 63     }
 64     int k=len;
 65     for(int i=n-1;i>=1;i--)
 66     {
 67         while(len>k&&Cross(t[len]-t[len-1],a[i]-t[len])<=0) len--;
 68         t[++len]=a[i];
 69     }len--;
 70     t[0]=t[len];
 71 }
 72
 73 void output()
 74 {
 75     for(int i=0;i<len;i++)
 76     {
 77         printf("%lf %lf\n",t[i].x,t[i].y);
 78     }printf("\n");
 79 }
 80
 81 double ans;
 82 P op[5];
 83
 84 void RC()
 85 {
 86     double L,R,H,D;
 87     ans=INF;
 88     int l=1,r=1,h=1;
 89     for(int i=0;i<len;i++)
 90     {
 91         int j=(i+1)%len;
 92         // l=i;r=j;h=j;
 93         // printf("%lf %lf\n",(t[h+1]-t[i]).x,(t[h+1]-t[i]).y);
 94         // printf("%lf %lf\n",(t[h+1]-t[j]).x,(t[h+1]-t[j]).y);
 95         while(Cross(t[h]-t[i],t[h]-t[j])<=Cross(t[h+1]-t[i],t[h+1]-t[j])) h=(h+1)%len;
 96         while(Dot(t[i]-t[j],t[r]-t[j])>=Dot(t[i]-t[j],t[r+1]-t[j])) r=(r+1)%len;
 97         if(i==0) l=r;
 98
 99         // printf("%lf %lf\n",Dot(t[j]-t[i],t[l]-t[i]),Dot(t[j]-t[i],t[l+1]-t[i]));
100         while(Dot(t[j]-t[i],t[l]-t[i])>=Dot(t[j]-t[i],t[l+1]-t[i])) l=(l+1)%len;
101
102         D=sqrt(Dot(t[i]-t[j],t[i]-t[j]));
103         H=Cross(t[h]-t[i],t[h]-t[j])/D;
104         L=-Dot(t[j]-t[i],t[l]-t[i])/D;
105         R=-Dot(t[i]-t[j],t[r]-t[j])/D;
106
107         // printf("**%lf %lf %lf %lf\n",D,H,L,R);
108
109         double now=(R+L+D)*H;
110         // printf("%lf %lf %d %d %d %lf\n",t[i].x,t[i].y,l,r,h,now);
111         if(now<ans)
112         {
113             ans=now;
114             op[0]=t[i]-(t[j]-t[i])*(L/D);
115             op[1]=t[j]-(t[i]-t[j])*(R/D);
116             P tt;
117             tt.x=(t[i]-t[j]).y;tt.y=-(t[i]-t[j]).x;
118             op[2]=op[1]+tt*(H/D);
119             op[3]=op[0]+tt*(H/D);
120             // op[0]=t[i];op[1]=t[j];op[2]=t[r];op[3]=t[l];
121         }
122     }
123 }
124
125 int main()
126 {
127     scanf("%d",&n);
128     for(int i=1;i<=n;i++)
129     {
130         scanf("%lf%lf",&a[i].x,&a[i].y);
131     }
132     chull();
133     // output();
134     RC();
135     int fr=0;
136     for(int i=1;i<4;i++) if(op[i].y<op[fr].y||fbs(op[fr].y-op[i].y)==0&&op[i].x<op[i].x) fr=i;
137     printf("%.5lf\n",ans);
138     for(int i=0;i<4;i++)
139     {
140         if(fbs(op[i].x)==0) op[i].x=0;
141         if(fbs(op[i].y)==0) op[i].y=0;
142     }
143     // for(int i=0;i<4;i++) op[i].x=myabs(op[i].x),op[i].y=myabs(op[i].y);
144     for(int i=0;i<4;i++)
145     {
146         printf("%.5lf %.5lf\n",op[(fr+i)%4].x,op[(fr+i)%4].y);
147     }
148     return 0;
149 }

调试过程不删了,心酸。。

2016-12-15 16:55:18

时间: 2024-10-26 09:44:47

【BZOJ 1185】 凸包+旋转卡壳的相关文章

【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle

[最小矩形面积覆盖:凸包+旋转卡壳]UVA 10173 Smallest Bounding Rectangle 题目链接:UVA 10173 Smallest Bounding Rectangle 题目大意 给你n个点,求能够覆盖所有点集的最小矩形面积. 笔者的第2道凸包题目,凸包 + 旋转卡壳,实现点集的最小矩形面积覆盖问题 ">=0"写成"<=0"坑了我一下午!QAQ 说一下思路 ①Graham's Scan法构建凸包,时间复杂度O(nlogn) ②

UVA 4728 Squares(凸包+旋转卡壳)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17267 [思路] 凸包+旋转卡壳 求出凸包,用旋转卡壳算出凸包的直径即可. [代码] 1 #include<cstdio> 2 #include<vector> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 struct Pt { 8

模板 凸包 旋转卡壳

模板  凸包  旋转卡壳 lrj <训练指南> P272 对于个点按照 x 从小到大排序,再按照 y 点从小到大排序,删除重复的点后,得到序列 p0,p1,p2..., 把 p0 和 p1 放入凸包. 从p2开始,当新点在凸包“前进”方向的左边时继续,否则依次删除最近加入凸包的点,直到新点在左边 PS:判断用叉积即可 1 /******************************************** 2 计算凸包,输入点数组 p, 个数为 n , 输出点数组 ch. 函数返回凸包顶

HDOJ 2202 最大三角形 凸包旋转卡壳求最大三角形面积

凸包旋转卡壳求最大三角形面积 最大三角形 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3316    Accepted Submission(s): 1119 Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角

hdu 3934&amp;&amp;poj 2079 (凸包+旋转卡壳+求最大三角形面积)

链接:http://poj.org/problem?id=2079 Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 8173   Accepted: 2423 Description Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices

BZOJ 1185 [HNOI2007]最小矩形覆盖:凸包 + 旋转卡壳

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 题意: 给出二维平面上的n个点,问你将所有点覆盖的最小矩形面积. 题解: 先找出凸包,然后旋转卡壳. 在旋转卡壳中有一个结论:最小覆盖矩形一定有一条边在凸包上. 所以先枚举矩形在凸包上的那条边(p[i],p[i+1]),然后利用单调性找出p[i]的对踵点p[u]. 至于左右两侧的切点p[l]和p[r],要利用它们连线在直线(p[i],p[i+1])上投影长度的单调性求出. 最后将

【BZOJ】1069: [SCOI2007]最大土地面积(凸包+旋转卡壳)

http://www.lydsy.com/JudgeOnline/problem.php?id=1069 显然这四个点在凸包上,然后枚举两个点找上下最大的三角形即可. 找三角形表示只想到三分QAQ....... 看了题解发现....这是单调的....直接扫...然后,这货叫“旋转卡壳”?是qia还是ka.... 自己一开始写的wa了........然后照标程写,,又wa了.... 后来发现是凸包写渣了QAQ...自己原来的找三角形是没问题的...我好sb..... 可是,为嘛凸包这样写会错. c

BZOJ 1069 SCOI 2007 最大土地面积 凸包+旋转卡壳

题目大意:给出平面上的一些点,求其中四个点的最大四边形的面积. 思路:简单yy一下发现这些点肯定都在凸包上,先求个凸包.然后直接暴力肯定是不行的,我们需要一个O(n^2)的做法,比较简单的想法是枚举最后要求的四边形的一条对线,那么这个四边形就被分割成了两个三角形,剩下两个点与这条线组成的三角形的面积和就是答案. 按照旋转卡壳的思想不难发现,这两个点都是单调的.所以枚举对角线然后扫n圈就可以了. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cm

HDU 5251 矩形面积(二维凸包旋转卡壳最小矩形覆盖问题) --2015百度之星题目

B - 矩形面积 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少. Input 第一行一个正整数 T,代表测试数据组数(),接下来 T 组测试数据. 每组测试数据占若干行,第一行一个正整数 ,代表矩形的数量.接下来 N 行,每行 8

poj 2079 Triangle 凸包+旋转卡壳

题意: 给平面上n个点,求这n个点组成的最大三角形面积. 分析: 旋转卡壳,但要注意和求平面最远点对的区别,最大三角形的边不一定在凸包上的,也贴出以前写的求平面最远点对的poj 2187代码作为对比. 代码: //poj 2079 //sep9 #include <iostream> #include <algorithm> using namespace std; const int maxN=50012; struct P { int x,y; }pnt[maxN],cnt[m