凸包 模板【uva10652】Board Wrapping

题目大意:
给定一些矩形,要求用面积最小的凸多边形覆盖这些矩形,求所有矩形占凸包面积百分比。

题目分析:
很显然就是把所有的矩形的顶点放在一起做个凸包求个面积就好了(本来这道题就是拿来写板子的啊)。
这个题唯一恶心的地方就是给矩形的方式丧心病狂,它给出了矩形的中心坐标,长,宽,和倾斜角(而且还TM是角度制)。
所以要把这个东西转成弧度制,再用数学知识推导(倒)这个矩形四个顶点的坐标。

其实本来没想总结一个板子的QAQ
但是昨天有个学长跟我讲:
说实话
你比赛是不是经常崩
你的代码有很大问题
首先你的凸包算法写的不是一个函数
很不好维护
导致了你的凸包的大小top没有初始化……

于是今天我把它写成了一个函数
代码如下:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define EPS 1e-8
#define N 10000
const double pi=acos(-1);
int cmp(double x)
{
    if(fabs(x)<EPS) return 0;
    if(x>0) return 1;
    return -1;
}
double to_rad(double x)
{
    return pi*x/180.0;
}
struct point{
    double x,y;
    point(double a=0,double b=0): x(a), y(b) {}
    bool operator < (const point &c) const { return cmp(x-c.x)<0 || (cmp(x-c.x)==0 && cmp(y-c.y)<0); } 
    point operator + (const point &c) const { return point(x+c.x,y+c.y); }
    point operator - (const point &c) const { return point(x-c.x,y-c.y); } 
    friend double det(const point &a,const point &b) { return a.x*b.y-a.y*b.x;}
}a[N],P[N];
int T,n,tot;
double x,y,w,h,fi;
double ans,sum;

void read()
{
    scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&fi);
    fi=to_rad(90.0-fi);
    point t=point(x,y);
    point t1=point(h*cos(fi)/2.0,h*sin(fi)/2.0);
    point t2=point(-t1.y*w/h,t1.x*w/h);
    a[++tot]=t+t1+t2;
    a[++tot]=t+t1-t2;
    a[++tot]=t-t1+t2;
    a[++tot]=t-t1-t2;
    sum+=w*h;
}
int convex_hull(point a[],point P[],int tot)
{
    sort(a+1,a+1+tot);
    int top=0;
    for(int i=1;i<=tot;++i)
    {
        while(top>1 && cmp(det(P[top]-P[top-1],a[i]-P[top-1]))<=0) --top;
        P[++top]=a[i];
    }
    int k=top;
    for(int i=tot-1;i>=1;--i)
    {
        while(top>k && cmp(det(P[top]-P[top-1],a[i]-P[top-1]))<=0) --top;
        P[++top]=a[i];
    }
    return top-1;
}
int main()
{
    scanf("%d",&T);
while(T--)
{
    sum=tot=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) read();
    int top=convex_hull(a,P,tot);
    ans=0;
    point O(0.0,0.0);
    for(int i=1;i<=top;i++)
        ans+=det(P[i]-O,P[i%top+1]-O);
    ans/=2.0;
    if(ans!=0)  ans=sum/ans*100.0;
    printf("%.1lf %%\n",ans);
}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值