zoukankan      html  css  js  c++  java
  • bzoj1185【HNOI2007】最小矩形覆盖

    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 ",mn); int fir=0; F(i,1,3) if (ans[i]<ans[fir]) fir=i; F(i,0,3) printf("%.5lf %.5lf ",ans[(i+fir)%4].x,ans[(i+fir)%4].y); return 0; }



  • 相关阅读:
    Java 读取txt文件,读取结果保存到数据库
    Java 读取大文件方法
    利用File类过滤器列出目录下的指定目录或文件
    Java 读取指定目录下的文件名和目录名
    利用js日期控件重构WEB功能
    简洁js日历控件的使用
    Tomcat中配置URIEncoding="UTF-8"来处理中文的方法
    Java MVC 增删改查 实例
    严重:The web application [web01] appears to have started a thread named ...
    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} 解决方法
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7253982.html
Copyright © 2011-2022 走看看