zoukankan      html  css  js  c++  java
  • Bzoj1185 [HNOI2007]最小矩形覆盖

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

    Description

     

    Input

     

    Output

     

    Sample Input

     

    Sample Output

     

    HINT

     

    Source

    数学问题 计算几何 旋转卡壳

    按顺序枚举凸包上每一条边为底边,旋转卡壳找出此时的矩形的顶点、最左点和最右点,花式计算出边长,求面积,记录面积最小值和对应的解。

    式子都能看懂,但不看题解就是写不出来,沮丧。

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int INF=0x3f3f3f3f;
     10 const double eps=1e-8;
     11 const int mxn=100010;
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 inline int DT(double x){
     19     if(abs(x)<eps)return 0;
     20     else return x<0?-1:1;
     21 }
     22 struct point{
     23     double x,y;
     24     point operator + (point b){return (point){x+b.x,y+b.y};}
     25     point operator - (point b){return (point){x-b.x,y-b.y};}
     26     point operator * (double v){return (point){x*v,y*v};}
     27     point operator / (double v){return (point){x/v,y/v};}
     28     bool operator < (point b)const{
     29         return x<b.x || (x==b.x && y<b.y);
     30     }
     31 }a[mxn],p[mxn],ans[5];
     32 typedef point Vector;
     33 double dot (point a,point b){return a.x*b.x+a.y*b.y;}
     34 double Cross(point a,point b){
     35     return a.x*b.y-a.y*b.x;
     36 }
     37 double dist(point a,point b){
     38     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     39 }
     40 double Len(point a){
     41     return sqrt((a.x*a.x)+(a.y*a.y));
     42 }
     43 double DLC(point p,point a,point b){
     44     Vector v1=p-a,v2=b-a;
     45     return fabs(Cross(v1,v2)/Len(v2));
     46 }
     47 int n;
     48 double ANS=0;
     49 int st[mxn],top=0,t2=0;
     50 void Andrew(){
     51     sort(p+1,p+n+1);
     52     for(int i=1;i<=n;i++){
     53         while(top>1 && Cross(p[st[top]]-p[st[top-1]],p[i]-p[st[top-1]])<=0)top--;
     54         st[++top]=i;
     55     }
     56     t2=top;
     57     for(int i=n-1;i;i--){
     58         while(t2>top && Cross(p[st[t2]]-p[st[t2-1]],p[i]-p[st[t2-1]])<=0)t2--;
     59         st[++t2]=i;
     60     }
     61     if(n>1)t2--;
     62     n=t2;
     63     for(int i=1;i<=n;i++){
     64         a[i]=p[st[i]];
     65     }
     66     return;
     67 }
     68 void solve(){
     69     ANS=(double)INF;
     70     a[n+1]=a[1];
     71     int l=1,r=1,tmp=1;
     72     double H,D,L,R;
     73     for(int i=1;i<=n;i++){
     74         while(DT(DLC(a[tmp],a[i],a[i+1])-DLC(a[tmp+1],a[i],a[i+1]))<=0)tmp=tmp%n+1;//顶部 
     75         while(DT(dot(a[i+1]-a[i],a[l]-a[i])-dot(a[i+1]-a[i],a[l+1]-a[i]))<=0)l=l%n+1;//左边 
     76         if(i==1)r=tmp;
     77         while(DT(dot(a[i+1]-a[i],a[r]-a[i])-dot(a[i+1]-a[i],a[r+1]-a[i]))>=0)r=r%n+1;//右边 
     78 //      printf("i:%d l:%d tmp:%d r:%d
    ",i,l,tmp,r);
     79         L=dist(a[i+1],a[i]);
     80 //      H=fabs(Cross(a[tmp]-a[i],a[i+1]-a[i]))/L;//
     81         H=DLC(a[tmp],a[i],a[i+1]);
     82         D=fabs(dot(a[i+1]-a[i],a[l]-a[i])/L)+fabs(dot(a[i+1]-a[i],a[r]-a[i])/L);//底边长 
     83         R=H*D;
     84 //      printf("L:%.3f H:%.3f D:%.3f R:%.3f
    ",L,H,D,R);
     85         if(R<ANS){//更新答案 
     86             ANS=R;
     87             Vector v=(a[i+1]-a[i])/L;//单位长度
     88             Vector u=(point){-v.y,v.x};//v逆时针转90度 
     89             ans[1]=a[i]+v*dot(a[r]-a[i],v);
     90             ans[2]=a[i]+v*dot(a[l]-a[i],v);
     91             ans[3]=ans[2]+u*H;
     92             ans[4]=ans[1]+u*H;
     93         }
     94     }
     95     return;
     96 }
     97 int main(){
     98 //  freopen("in.txt","r",stdin);
     99     int i,j;
    100     scanf("%d",&n);
    101     for(i=1;i<=n;i++){
    102         scanf("%lf%lf",&p[i].x,&p[i].y);
    103     }
    104     Andrew();
    105 /*  printf("n:%d
    ",n);
    106     for(i=1;i<=n;i++){
    107         printf("%.3f  %.3f
    ",a[i].x,a[i].y);
    108     }*/
    109     solve();
    110     int pos=1;
    111     for(i=1;i<=4;i++){
    112         if(ans[i].y<eps)ans[i].y=0;
    113         if(ans[i].x<eps)ans[i].x=0;
    114         if(ans[i].y<ans[pos].y || (ans[i].y==ans[pos].y && ans[i].x<ans[pos].x))pos=i;
    115     }
    116     if(ANS<eps)ANS=0;
    117     printf("%.5f
    ",ANS);
    118     for(i=pos;i<=4;i++)
    119         printf("%.5f %.5f
    ",ans[i].x,ans[i].y);
    120     for(i=1;i<pos;i++)
    121         printf("%.5f %.5f
    ",ans[i].x,ans[i].y);
    122     return 0;
    123 }
  • 相关阅读:
    1040 最大公约数之和
    51nod 1215 数组的宽度
    51nod 1423 最大二“货” 单调栈
    51nod 1437 迈克步 单调栈
    1564 区间的价值
    51nod 1294 修改数组
    51nod1693 水群 最短路
    51nod1052 最大M子段和
    我不管,这就是水题《1》
    河工大校赛 Hmz 的女装 http://218.28.220.249:50015/JudgeOnline/problem.php?id=1265
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6686551.html
Copyright © 2011-2022 走看看