poj2451 Uyuw's Concert【半平面交】

74 篇文章 0 订阅
33 篇文章 0 订阅

题目链接:http://poj.org/problem?id=2451
题意:在一个[0,10000]*[0,10000]的矩形里面做线性规划,让你求线性规划后的区域部分的面积
解析:半平面交求面积,直接套模板

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const double eps = 1e-6;
const int maxn = 1e5+100;
int dblcmp(double x)
{
    if(fabs(x)<eps)
        return 0;
    return x>0?1:-1;
}
struct point
{
    double x,y;
    point () {}
    point(double _x,double _y)
    {
        x = _x;
        y = _y;
    }
}ans[maxn];
struct line
{
    point s,e;
    double angle;
    line() {}
    line(point _s,point _e)
    {
        s = _s;
        e = _e;
        angle = atan2(e.y-s.y,e.x-s.x);
    }
}l[maxn],deq[maxn];
int head,tail,it;
double x_mul(point p0,point p1,point p2)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
point cross(line u,line v)
{
    point ret = u.s;
    double t = ((u.s.x-v.s.x)*(v.s.y-v.e.y)
               -(u.s.y-v.s.y)*(v.s.x-v.e.x))
             / ((u.s.x-u.e.x)*(v.s.y-v.e.y)
               -(u.s.y-u.e.y)*(v.s.x-v.e.x));
    ret.x += (u.e.x-u.s.x)*t, ret.y += (u.e.y-u.s.y)*t;
    return ret;
}
bool cmp(line u,line v)
{
    //极角排序
    int tmp = dblcmp(u.angle-v.angle);
    if(tmp)
        return tmp>0;
    return dblcmp(x_mul(u.s,v.s,v.e))>0;
    //Clockwise:大于0取向量左半部分为半平面,小于0,取右半部分
}
bool judge(line l1,line l2,line l3)
{
    point p = cross(l2,l3);
    return dblcmp(x_mul(p,l1.s,l1.e))<0;
    //Clockwise:大于小于符号与上面cmp()中注释处相反
}
void HPI(line l[],int n)
{
    //nlgn算法
    sort(l,l+n,cmp);
    int tmp = 1;
    for(int i=1;i<n;i++)
    {
        if(dblcmp(l[i].angle-l[tmp-1].angle)!=0)
            l[tmp++] = l[i];
    }
    n = tmp;
    deq[0] = l[0],deq[1] = l[1];
    head = 0,tail = 1;
    for(int i=2;i<n;i++)
    {
        while(head<tail && judge(l[i],deq[tail-1],deq[tail]))
            tail--;
        while(head<tail && judge(l[i],deq[head+1],deq[head]))
            head++;
        deq[++tail] = l[i];
    }
    while(head<tail && judge(deq[head],deq[tail-1],deq[tail]))
        tail--;
    while(head<tail && judge(deq[tail],deq[head+1],deq[head]))
        head++;
    if(head==tail)
        return ;
    it = 0;
    for(int i=head;i<tail;i++)
        ans[it++] = cross(deq[i],deq[i+1]);
    if(tail>head+1)
        ans[it++] = cross(deq[head],deq[tail]);
}
bool isThereACore()
{
    //判断多边形是否有核
    if(tail-head>1)
        return true;
    return false;
}
double getArea(point p[],int n)
{
    //求线性规划面积
    double area = 0;
    for(int i=1;i<n-1;i++)
        area += x_mul(p[i+1],p[0],p[i]);
    return fabs(area)/2.0;
}

int main(void)
{
    int n;
    while(~scanf("%d",&n))
    {
        n += 4;
        l[0] = (line){(point){0, 10000}, (point){0, 0}};
        l[1] = (line){(point){10000, 10000}, (point){0, 10000}};
        l[2] = (line){(point){10000, 0}, (point){10000, 10000}};
        l[3] = (line){(point){0, 0}, (point){10000, 0}};
        for(int i = 4; i < n; ++i)
        {
            point p1,p2;
            scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
            l[i] = line(p1,p2);
        }
        HPI(l,n);
        printf("%.1f\n", getArea(ans,it));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值