您的位置:首页 > 其它

bzoj1185[HNOI2007]最小矩形覆盖

2015-12-02 19:43 260 查看
啊啊啊啊啊啊啊啊手速不行啊打了好久啊好吧其实也想了好久

这道题真是神奇WA了好几次= =结果还是因为看错题

我们可以做个凸包,然后这个矩形上一定有点,而且不止一个,所以只有一个点的一定不是最优的,这样的话我们就可以枚举一个凸包上面的点(因为点太多23333333不然我就枚举对角线了),然后我们可以用叉积来卡这个点对面的点,用点积来卡两边的店,这样我们就可以用旋转卡壳来完美卡住这个矩形

至于输出,真的好麻烦愣是调了40分钟

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
#define N 50005
#define eps 1e-8
struct dian
{
double x,y;
}d
,ch
,ans[5];
double ansarea=0.0;
int n;

double cross(dian a,dian b,dian c)
{
dian xlab,xlac;
xlab.x=b.x-a.x;
xlab.y=b.y-a.y;
xlac.x=c.x-a.x;
xlac.y=c.y-a.y;
return (xlab.x*xlac.y)-(xlac.x*xlab.y);
}

double dj(dian a,dian b,dian c)
{
dian xlab,xlac;
xlab.x=b.x-a.x;
xlab.y=b.y-a.y;
xlac.x=c.x-a.x;
xlac.y=c.y-a.y;
return (xlab.x*xlac.x)+(xlab.y*xlac.y);
}

double dis(dian a,dian b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

bool sortcom(dian a,dian b)
{
double t=cross(d[1],a,b);
if (fabs(t)<eps) return dis(d[1],a)-dis(d[1],b)<eps;
return t>0;
}

bool xy(dian a,dian b)
{
if (fabs(a.x-b.x)<=eps) return (a.y-b.y<eps);
else return (a.x-b.x<eps);
}

bool yx(dian a,dian b)
{
if (fabs(a.y-b.y)<eps) return (a.x-b.x<eps);
else return (a.y-b.y<eps);
}

dian add(dian a,dian b)
{
dian t;
t.x=a.x+b.x;
t.y=a.y+b.y;
return t;
}

dian minu(dian a,dian b)
{
dian t;
t.x=a.x-b.x;
t.y=a.y-b.y;
return t;
}

dian dcheng(dian a,double b)
{
dian t;
t.x=a.x*b;
t.y=a.y*b;
return t;
}

int s
,top=0;
void graham()
{
fo(i,2,n)
if(yx(d[i],d[1])) swap(d[i],d[1]);
sort(d+2,d+n+1,sortcom);
s[++top]=1;
fo(i,2,n)
{
while (top>1&&cross(d[s[top-1]],d[s[top]],d[i])<eps)top--;
s[++top]=i;
}
s[0]=s[top];
fo(i,0,top) ch[i]=d[s[i]];
// cout<<top<<endl;
// fo(i,1,top) cout<<ch[i].x<<' '<<ch[i].y<<endl;
}

//int q[5];
void getans(int i,int l,int up,int r)
{
double D,H,L,R,B,S;
D=dis(ch[i],ch[i+1]);
L=dj(ch[i],ch[i+1],ch[l])/D;
R=dj(ch[i],ch[i+1],ch[r])/D;
// B=(L+R)-D;
B=R-L;
H=fabs(cross(ch[i],ch[i+1],ch[up]))/D;
S=H*B;
// cout<<i<<' '<<l<<' '<<up<<' '<<r<<' '<<L<<' '<<R<<' '<<S<<' '<<ansarea<<endl;
if (S-ansarea<eps||fabs(ansarea)<eps)
{
ans[0]=add(ch[i],dcheng(minu(ch[i+1],ch[i]),(R/D)));
ans[1]=add(ans[0],dcheng(minu(ch[r],ans[0]),(H/dis(ans[0],ch[r]))));
ans[2]=minu(ans[1],dcheng(minu(ans[0],ch[i]),((R-L)/dis(ch[i],ans[0]))));
ans[3]=minu(ans[2],minu(ans[1],ans[0]));
ansarea=S;
}
}

void RC()
{
int up=1,l=1,r=1;
fo(i,0,top-1)
{
while(cross(ch[i],ch[i+1],ch[up+1])-cross(ch[i],ch[i+1],ch[up])>-eps)
up=(up+1)%top;
while(dj(ch[i],ch[i+1],ch[r+1])-dj(ch[i],ch[i+1],ch[r])>-eps)
r=(r+1)%top;
if (i==0) l=r;
while(dj(ch[i],ch[i+1],ch[l+1])-dj(ch[i],ch[i+1],ch[l])<eps)
l=(l+1)%top;
getans(i,l,up,r);
}
}

int main()
{
// freopen("data.in","r",stdin);
scanf("%d",&n);
fo(i,1,n) scanf("%lf%lf",&d[i].x,&d[i].y);
graham();
RC();
int st=0;dian mi=ans[0];
fo(i,1,3)
if (yx(ans[i],mi)) st=i;
cout<<setiosflags(ios::fixed);
cout.precision(5);
cout<<ansarea<<endl;
fo(i,st,st+4)
if (i%5==4) continue;
else cout<<ans[i%5].x<<' '<<ans[i%5].y<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  计算几何 NOIP