poj 5251(凸包 旋转卡壳)最小矩形面积

11 篇文章 0 订阅
3 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=5251


集合叉积与点积的应用

#include<stdio.h>  
#include<string.h>  
#include<algorithm>  
#include<math.h>  
using namespace std;

#define N 10100  
#define maxdouble 1e20  
struct Point
{
    double x, y;
    bool operator < (const Point& other) const{
        if (y != other.y)
            return y < other.y;
        return x < other.x;
    }
};
struct TPolygon
{
    int n;
    Point p[N];
}ply;
double MIN(double a, double b) { return a>b ? b : a; }
double dist(Point a, Point b){//距离  
    return sqrt((b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y));
}
double cross(Point a, Point b, Point c){//叉积  
    return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}
double dot(Point a, Point b, Point c){//点积  
    return (b.x - a.x)*(c.x - a.x) + (b.y - a.y)*(c.y - a.y);
}
bool cmp(Point a, Point b){return cross(ply.p[0], a, b)>0;}

int main()
{
    int xp = 1;
    int numx;
    scanf("%d", &numx);
    while (numx--){
        scanf("%d", &ply.n);
        int i;
        double area;
        ply.n *= 4;
        for(i = 0; i<ply.n; i++) scanf("%lf%lf", &ply.p[i].x, &ply.p[i].y);
        sort(ply.p, ply.p + ply.n);//排序  
        sort(ply.p + 1, ply.p + ply.n, cmp);
        int j;
        for(j = i = 2; i<ply.n; i++){
            while (j>1 && cross(ply.p[j - 2], ply.p[i], ply.p[j - 1]) >= 0) j--;
            ply.p[j++] = ply.p[i];
        }
        ply.n = j;
        if (ply.n<3) area = 0;
        else {
            int top = 1, right = 1, left;
            double minarea = maxdouble, _area;
            ply.p[ply.n] = ply.p[0];
            for(i = 0; i<ply.n; i++){
                while (cross(ply.p[i], ply.p[i + 1], ply.p[top+ 1])//最上一点  
                    - cross(ply.p[i], ply.p[i + 1], ply.p[top])>0)
                    top = (top + 1) % ply.n;
                while (dot(ply.p[i], ply.p[i + 1], ply.p[right + 1])//最右一点  
                    - dot(ply.p[i], ply.p[i + 1], ply.p[right]) > 0)
                    right = (right + 1) % ply.n;
                if (i == 0) left= right;
                while (dot(ply.p[i], ply.p[i + 1], ply.p[left+ 1])//最左一点  
                    - dot(ply.p[i], ply.p[i + 1], ply.p[left]) <= 0)
                    left= (left+ 1) % ply.n;
                double d = dist(ply.p[i], ply.p[i + 1])*dist(ply.p[i], ply.p[i + 1]);
                _area = cross(ply.p[i], ply.p[i + 1], ply.p[top])*//求面积  
                    (dot(ply.p[i], ply.p[i + 1], ply.p[right]) - dot(ply.p[i], ply.p[i + 1], ply.p[left])) / d;
                minarea = MIN(_area, minarea);//更新  
            }
            area = minarea;
        }
        printf("Case #%d:\n%.0lf\n", xp++, area);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值