码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1185【HNOI2007】最小矩形覆盖

时间:2016-04-19 06:31:48      阅读:389      评论:0      收藏:0      [点我收藏+]

标签:

1185: [HNOI2007]最小矩形覆盖

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 1114  Solved: 505
[Submit][Status][Discuss]

Description

技术分享 

技术分享





凸包+旋转卡壳

首先有一个结论:矩形一定有一条边在凸包上,否则我们旋转之后一定会得到一个更小的矩形,脑补一下。

然后枚举凸包上的边,用旋转卡壳维护矩形的另外三条边,同时更新答案即可。




#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 50005
#define eps 1e-8
#define inf 1e60
using namespace std;
int n,top;
double mn=inf;
struct data
{
	double x,y;
	friend bool operator ==(data a,data b){return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;}
	friend bool operator !=(data a,data b){return !(a==b);}
	friend bool operator <(data a,data b){return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;}
	friend bool operator >(data a,data b){return !(a==b)&&!(a<b);}
	friend data operator +(data a,data b){return (data){a.x+b.x,a.y+b.y};}
	friend data operator -(data a,data b){return (data){a.x-b.x,a.y-b.y};}
	friend double operator *(data a,data b){return a.x*b.y-a.y*b.x;}//叉积 
	friend double operator /(data a,data b){return a.x*b.x+a.y*b.y;}//点积 
	friend data operator *(data a,double b){return (data){a.x*b,a.y*b};}
}p[maxn],s[maxn],ans[4];
inline double dis(data a,data b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline bool cmp(data a,data b)
{
	double t=(a-p[1])*(b-p[1]);
	if (fabs(t)<eps) return (dis(a,p[1])<dis(b,p[1]));
	else return t>0;
}
inline void solve()
{
	F(i,2,n) if (p[i]<p[1]) swap(p[1],p[i]);
	sort(p+2,p+n+1,cmp);
	s[++top]=p[1];
	F(i,2,n)
	{
		while (top>1&&(p[i]-s[top-1])*(s[top]-s[top-1])>-eps) top--;
		s[++top]=p[i];
	}
}
inline void getans()
{
	int l=1,r=1,p=1;
	double L,R,D,H;
	s[0]=s[top];
	F(i,0,top-1)
	{
		D=dis(s[i],s[i+1]);
		while ((s[i+1]-s[i])*(s[p+1]-s[i])-(s[i+1]-s[i])*(s[p]-s[i])>-eps) p=(p+1)%top;
		while ((s[i+1]-s[i])/(s[r+1]-s[i])-(s[i+1]-s[i])/(s[r]-s[i])>-eps) r=(r+1)%top;
		if (i==0) l=r;
		while ((s[i+1]-s[i])/(s[l+1]-s[i])-(s[i+1]-s[i])/(s[l]-s[i])<eps) l=(l+1)%top;
		L=((s[i+1]-s[i])/(s[l]-s[i]))/D;
		R=((s[i+1]-s[i])/(s[r]-s[i]))/D;
		H=abs((s[i+1]-s[i])*(s[p]-s[i]))/D;
		if ((R-L)*H<mn)
		{
			mn=(R-L)*H;
			ans[0]=s[i]+(s[i+1]-s[i])*(R/D);
			ans[1]=ans[0]+(s[r]-ans[0])*(H/dis(s[r],ans[0]));
			ans[2]=ans[1]+(s[i]-ans[0])*((R-L)/dis(s[i],ans[0]));
			ans[3]=ans[2]+(ans[0]-ans[1]);
		}
	}
}
int main()
{
	scanf("%d",&n);
	F(i,1,n) scanf("%lf%lf",&p[i].x,&p[i].y);
	solve();
	getans();
	printf("%.5lf\n",mn);
	int fir=0;
	F(i,1,3) if (ans[i]<ans[fir]) fir=i;
	F(i,0,3) printf("%.5lf %.5lf\n",ans[(i+fir)%4].x,ans[(i+fir)%4].y);
	return 0;
}


bzoj1185【HNOI2007】最小矩形覆盖

标签:

原文地址:http://blog.csdn.net/aarongzk/article/details/51184925

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!