BZOJ 1185 [HNOI2007]最小矩形覆盖
2016-09-29 15:19
351 查看
凸包+旋转卡壳
结论:一个凸包的最小矩形覆盖一定有一条边在凸包上
证明?打表/对拍证明吧。。。(反正我不会证,为什么都说它是显而易见的?)
然后跑凸包,枚举边,旋转卡壳找点搞一搞就好了
结论:一个凸包的最小矩形覆盖一定有一条边在凸包上
证明?打表/对拍证明吧。。。(反正我不会证,为什么都说它是显而易见的?)
然后跑凸包,枚举边,旋转卡壳找点搞一搞就好了
#include<cmath> #include<cstdio> #include<algorithm> #define calc(a,b,c) cross(p[b]-p[a],p[c]-p[a]) #define N 50005 using namespace std; struct point { double x, y; point operator - (point a) { return (point){x-a.x,y-a.y}; } point operator + (point a) { return (point){x+a.x,y+a.y}; } point operator * (double a) { return (point){x*a,y*a}; } point operator / (double a) { return (point){x/a,y/a}; } }p , print[4]; const double eps = 1e-8; double ans=10000000000000000.0; int n, con , top; bool cmp(point a, point b) { return a.x<b.x||(a.x==b.x && a.y<b.y); } double cross(point a, point b) { return a.x*b.y-a.y*b.x; } double dot(point a, point b) { return a.x*b.x+a.y*b.y; } void Convex() { sort(p+1,p+1+n,cmp); top=0; for(int i = 1; i <= n; i++) { while(top>1 && calc(con[top-2],i,con[top-1]) >= 0)top--; con[top++]=i; } int temp=top; for(int i = n-1; i >= 1; i--) { while(top>temp && calc(con[top-2],i,con[top-1]) >= 0)top--; con[top++]=i; } con[top]=con[0]; top--; } double dis(point a, point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void rotate() { int up=1, left=1, right=1; for(int i = 0; i < top; i++) { while(calc(con[i],con[i+1],con[up])<calc(con[i],con[i+1],con[up+1]))up=(up+1)%top; while(dot(p[con[i]]-p[con[left]],p[con[i+1]]-p[con[i]]) < 0 || dot(p[con[i]]-p[con[left]],p[con[i+1]]-p[con[i]])<dot(p[con[i]]-p[con[left+1]],p[con[i+1]]-p[con[i]]))left=(left+1)%top; while(dot(p[con[i+1]]-p[con[right]],p[con[i]]-p[con[i+1]])<dot(p[con[i+1]]-p[con[right+1]],p[con[i]]-p[con[i+1]]))right=(right+1)%top; double la=dis(p[con[i]],p[con[i+1]]); double RRR=dot((p[con[right]]-p[con[i]]),(p[con[i+1]]-p[con[i]]))/la; double LLL=dot((p[con[left]]-p[con[i]]),(p[con[i+1]]-p[con[i]]))/la; if(LLL<0)LLL=-LLL; double length=LLL+RRR; double height=cross((p[con[i+1]]-p[con[i]]),(p[con[up]]-p[con[i]]))/la; if(height*length<ans) { ans=height*length; print[0]=p[con[i]]+((p[con[i+1]]-p[con[i]])*(RRR/la)); print[1]=print[0]+(p[con[right]]-print[0])*(height/dis(p[con[right]],print[0])); print[2]=print[1]+(p[con[up]]-print[1])*(length/dis(p[con[up]],print[1])); print[3]=print[2]+(p[con[left]]-print[2])*(height/dis(p[con[left]],print[2])); } } } int main() { scanf("%d",&n); for(int i = 1; i <= n; i++) scanf("%lf%lf",&p[i].x,&p[i].y); Convex(); rotate(); printf("%.5lf\n",ans); int pre=0; for(int i=1;i<=3;i++) { if(print[i].y<print[pre].y)pre=i; else if(fabs(print[i].y-print[pre].y)<eps&&print[i].x<print[pre].x)pre=i; } for(int i=0;i<4;i++) printf("%.5lf %.5lf\n",print[(pre+i)%4].x,print[(pre+i)%4].y); }
相关文章推荐
- bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳
- bzoj 1185: [HNOI2007]最小矩形覆盖 (旋转卡壳)
- BZOJ1185 [HNOI2007]最小矩形覆盖
- BZOJ 1185([HNOI2007]最小矩形覆盖-旋转卡壳+点集几何意义)
- BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳
- [BZOJ1185][HNOI2007]最小矩形覆盖(凸包+旋转卡壳)
- [BZOJ1185][HNOI2007]最小矩形覆盖(计算几何-旋转卡壳)
- 【HNOI2007】bzoj1185 最小矩形覆盖
- BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
- BZOJ 1185: [HNOI2007]最小矩形覆盖
- BZOJ 1185 [HNOI2007]最小矩形覆盖 ——计算几何
- Bzoj1185 [HNOI2007]最小矩形覆盖
- BZOJ 1185 HNOI 2007 最小矩形覆盖 旋转卡壳
- BZOJ1185 : [HNOI2007]最小矩形覆盖
- [省选前题目整理][BZOJ 1185][HNOI 2007]最小矩形覆盖(旋转卡壳)
- BZOJ1185 [HNOI2007]最小矩形覆盖
- bzoj1185 [HNOI2007]最小矩形覆盖
- 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
- ●BZOJ 1185 [HNOI2007]最小矩形覆盖