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

【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle

时间:2015-08-02 23:28:37      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:凸包   旋转卡壳   最小矩形面积覆盖   

【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle

题目链接:UVA 10173 Smallest Bounding Rectangle

题目大意

给你n个点,求能够覆盖所有点集的最小矩形面积。

技术分享
技术分享

笔者的第2道凸包题目,凸包  + 旋转卡壳,实现点集的最小矩形面积覆盖问题
“>=0”写成”<=0“坑了我一下午!QAQ

技术分享

说一下思路

  • ①Graham’s Scan法构建凸包,时间复杂度O(nlogn)
  • ②利用旋转卡壳的思想,最小矩形至少存在一条边与凸包共线。所以直接枚举底边,利用旋转卡壳确定其余三个点即可(kuangbin的最小矩形覆盖模板,但操作函数我在结构体外定义,省空间!)

参考代码

/*====================================*|*          最小矩形面积覆盖          *|
|* 多边形A必须是凸包(默认:逆时针顺序)*|
\*====================================*/
/*Author:Hacker_vision*/
#include<bits/stdc++.h>
#define eps 1e-8
using namespace  std;

const int _max = 1e3 + 10;
const double PI = acos(-1);
int n;

int sgn(double x){//三态函数
  if(fabs(x)<eps) return 0;else return x<0?-1:1;
}

struct point{double x,y;}p[_max],res[_max];

bool mult(point sp,point ep,point op){
  return (sp.x - op.x) * (ep.y - op.y)
       >= (ep.x - op.x) * (sp.y - op.y);
}

bool operator < (const point &l, const point &r){
   return l.y < r.y ||(l.y == r.y && l.x < r.x);
}

int graham(point pnt[],int n, point res[]){//构造凸包
  int i,len ,k = 0,top = 1;
  sort(pnt,pnt+n);
  if(n == 0)return 0; res[0] = pnt[0];
  if(n == 1)return 1; res[1] = pnt[1];
  if(n == 2)return 2; res[2] = pnt[2];
  for(int i =2; i < n; ++ i){
    while(top && mult(pnt[i],res[top],res[top-1]))
        top--;
    res[++top] = pnt[i];
  }
  len = top; res[++top] = pnt[n - 2];
  for(i = n - 3; i >= 0; -- i){
    while(top!=len && mult(pnt[i],res[top],res[top-1]))
        top--;
    res[++top] = pnt[i];
  }
  return top;//返回凸包中点的个数
}

double len(point A,point B){//返回向量AB的模平方
  return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}

double dot(point A,point B,point C){//点乘
  return (C.x-A.x)*(B.x-A.x)+(C.y-A.y)*(B.y-A.y);
}

double cross(point A,point B,point C){//叉乘
  return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}

double minRetangleCover(){//最小矩形面积覆盖(旋转卡壳)
  if(n < 3) return 0.0;
  res[n] = res [0];
  double ans = -1;
  int r = 1, p = 1,q;
   for(int i = 0; i < n; ++ i){
    //卡出离边 res[i]-res[i+1]最远的点
    while(sgn(cross(res[i],res[i+1],res[r+1])-cross(res[i],res[i+1],res[r]))>=0)
        r = (r+1)% n;
    //卡出res[i]-res[i+1]方向上正向n最远的点
    while(sgn(dot(res[i],res[i+1],res[p+1])-dot(res[i],res[i+1],res[p]))>=0)
        p = (p+1)% n;
    if(i == 0) q = p;
    //卡出res[i]-res[i+1]方向上负向最远的点
    while(sgn(dot(res[i],res[i+1],res[q+1])-dot(res[i],res[i+1],res[q]))<=0)
        q = (q+1)% n;
    double d = len(res[i],res[i+1]);
    double temp = cross(res[i],res[i+1],res[r])*(dot(res[i],res[i+1],res[p])-dot(res[i],res[i+1],res[q]))/d;
    if(ans < 0 || ans > temp) ans = temp;
  }
  return ans;
}

int main(){
  #ifndef ONLINE_JUDGE
  freopen("input.txt","r",stdin);
  #endif // ONLINE_JUDGE
  while(scanf("%d",&n)==1 && n){
    for(int i = 0; i < n; ++ i){
        scanf("%lf%lf",&p[i].x,&p[i].y);
    }
    n = graham(p,n,res);//构造凸包
    printf("%.4f\n",minRetangleCover());
  }
  return 0;
}
  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

版权声明:本文为博主原创文章,未经博主允许不得转载。

【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle

标签:凸包   旋转卡壳   最小矩形面积覆盖   

原文地址:http://blog.csdn.net/u012717411/article/details/47212213

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