UVA 10652 Board Wrapping(计算几何基础,求凸包)

题目链接:传送门

分析:

没有什么好说的就是求一个凸包就好了。可以当作模板、

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const double eps = 1e-10;

//判断符号,提高精度
int dcmp(double x){
    if(fabs(x)<eps) return 0;
    else return x < 0 ? -1 : 1;
}

struct Point{
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) { }
    bool operator < (const Point& a) const{
        if(a.x != x) return x < a.x;
        return y < a.y;
    }
    bool operator == (const Point B)const{
        return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;
    }
};

typedef Point Vector;
Vector operator + (Vector A, Vector B){
    return Vector(A.x+B.x, A.y+B.y);
}
Vector operator - (Point A, Point B){
    return Vector(A.x-B.x, A.y-B.y);
}
Vector operator * (Vector A, double p){
    return Vector(A.x*p, A.y*p);
}
Vector operator / (Vector A, double p){
    return Vector(A.x/p, A.y/p);
}
double Dot(Vector A, Vector B){//向量相乘
    return A.x*B.x + A.y*B.y;  //a*b*cos(a,b)
}
double Length(Vector A){
    return sqrt(Dot(A, A));    //向量的长度
}
double Angle(Vector A, Vector B){
    return acos(Dot(A, B) / Length(A) / Length(B));    //向量的角度
}
double Cross(Vector A, Vector B){//叉积
    return A.x*B.y - A.y*B.x;
}

/**
向量(x,y) 绕起点逆时针旋转a度。
x' = x*cosa - y*sina
y' = x*sina + y*cosa
**/
Vector Rotate(Vector A,double a){
    return Vector (A.x*cos(a)-A.y*sin(a),A.x*sin(a)+A.y*cos(a));
}

double trans(double ang){
    return ang/180*acos(-1.0);
}

//叉积,可以用来判断方向和求面积
double cross(Point a,Point b,Point c){
    return (c.x-a.x)*(b.y-a.y) - (b.x-a.x)*(c.y-a.y);
}

//求多边形的面积
double S(Point p[],int n)
{
    double ans = 0;
    p[n] = p[0];
    for(int i=1; i<n; i++)
        ans += cross(p[0],p[i],p[i+1]);
    if(ans < 0) ans = -ans;
    return ans / 2.0;
}

/**
求二维凸包Andrew算法,将所有的点按x小到大(x相等,y小到大)排序
删去重复的点,得到一个序列p1,p2...,然后把p1,p2放入凸包中,从p3
开始当新点再前进方向左边时(可以用叉积判断方向)继续,否则,依次
删除最近加入凸包的点,直到新点再左边。
**/

int ConvexHull(Point *p,int n,Point *stack){
    sort(p,p+n);
    n=unique(p,p+n)-p;
    int m=0;
    for(int i=0; i<n; i++) {//如果不希望凸包的边上有输入的点则把两个等号去掉
        while(m>1&&cross(stack[m-2],p[i],stack[m-1])<=0) m--;
        stack[m++]=p[i];
    }
    int k=m;
    for(int i=n-2; i>=0; i--){
        while(m>k&&cross(stack[m-2],p[i],stack[m-1])<=0)m--;
        stack[m++]=p[i];
    }
    if(n>1) m--;
    return m;
}

Vector p[2500];
Vector st[2500];

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        double x,y,w,h,a;
        int num = 0;
        double tot = 0;
        for(int i=0; i<n; i++){
            scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&a);
            double ang = -trans(a);
            Point o = Point(x,y);
            p[num++] = o + Rotate(Point(-w/2,-h/2),ang);
            p[num++] = o + Rotate(Point(w/2,-h/2),ang);
            p[num++] = o + Rotate(Point(-w/2,h/2),ang);
            p[num++] = o + Rotate(Point(w/2,h/2),ang);
            tot+=w*h;
        }
        int m = ConvexHull(p,num,st);
        double area = S(st,m);
        printf("%.1lf %%\n",tot*100/area);
    }
    return 0;
}

/****

1
4
4 7.5 6 3 0
8 11.5 6 3 0
9.5 6 6 3 90
4.5 3 4.4721 2.2361 26.565

****/

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

时间: 2024-10-07 07:34:12

UVA 10652 Board Wrapping(计算几何基础,求凸包)的相关文章

uva 10652 Board Wrapping (计算几何-凸包)

Problem B Board Wrapping Input: standard input Output: standard output Time Limit: 2 seconds The small sawmill in Mission, British Columbia, has developed a brand new way of packaging boards for drying. By fixating the boards in special moulds, the b

Uva 10652 Board Wrapping

二次联通门 : Virtual Judge Uva 10652 Board Wrapping /* Uva 10652 Board Wrapping 计算几何 将每个家具拆为4个点 对所有点求一个凸包 然后求凸包的面积即可 思路不难.. 但是写起来好麻烦好麻烦 需要注意的东西有很多 1. 角度制转弧度制 2. EPS的选择 3. PI的取值 (以防万一以后还是都写acos(-1)吧...) 4. 在把家具拆成四个点时的细节 4. 计算多边形的面积 */ #include <algorithm>

Uva - 10652 Board Wrapping(凸包)

给定一些长方形的坐标,求长方形的面积与围住这些长方形面积的凸包的百分比. 首先假设长方形都是水平放置,那么根据长和宽还有中心坐标,可以求出四个顶点的坐标,然后求出从中心指向顶点的向量,和角度转化成的弧度,向量旋转之后得到一个新的向量 是由中心指向新的顶点,加上中心点就得到新的顶点的坐标.可以画图理解. 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm&

UVA 10652 Board Wrapping 计算几何

多边形凸包.... Board Wrapping Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem B Board Wrapping Input: standard input Output: standard output Time Limit: 2 seconds The small sawmill in Mission, Britis

简单几何(向量旋转+凸包+多边形面积) UVA 10652 Board Wrapping

题目传送门 题意:告诉若干个矩形的信息,问他们在凸多边形中所占的面积比例 分析:训练指南P272,矩形面积长*宽,只要计算出所有的点,用凸包后再求多边形面积.已知矩形的中心,向量在原点参考点再旋转,角度要转换成弧度制. /************************************************ * Author :Running_Time * Created Time :2015/11/10 星期二 10:34:43 * File Name :UVA_10652.cpp

UVA 10652 Board Wrapping(凸包)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32286 [思路] 凸包 根据角度与中心点求出长方形所有点来,然后就可以应用凸包算法了. [代码] #include<cmath> #include<cstdio> #include<algorithm> using namespace std; const double PI = acos(-1.0); double torad(doub

UVA 10652 Board Wrapping(二维凸包)

传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组先输入木板个数n,接下来n行,每行x,y,w,h,j.(x,y)是木板中心的坐标,w是宽,h是高,j是顺时针旋转的角度. 木板互不相交. 输出:对于每组数据,输出木板总面积占包装总面积的百分比,保留小数点后1位. 题解:典型的二维凸包问题,理解并调用模板即可. #include <math.h>

Board Wrapping(计算几何求凸包加向量的旋转)

UVA - 10652 Board Wrapping Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   [Go Back]   [Status] Description Problem B Board Wrapping Input: standard input Output: standard output Time Limit: 2 seconds The small sa

【UVA10652】Board Wrapping(求凸包面积)

点此看题面 大致题意: 告诉你若干个矩形的重心坐标.长.宽和相对\(y\)轴的偏转角度,求矩形面积和与能围住这些矩形的最小凸包面积之比. 矩形面积和 这应该是比较好求的吧. 已经给了你长和宽,直接乘起来累加即可. 最小凸包面积 这道题关键还是在于求凸包面积. 首先,我们要注意将题目中给出的角度转换成弧度,还要记得取相反数,不然调死你. 这段代码可以与旋转函数放在一起: inline Point Rotate(Vector A,double deg) { register double rad=d