半平面交模板

网上搜刮来的模板

题目:
POJ 3335 Rotating Scoreboard
POJ 1474 Video Surveillance
POJ 1279 Art Gallery
POJ 3525 Most Distant Point from the Sea
POJ 3384 Feng Shui
POJ 1755 Triathlon
POJ 2540 Hotter Colder
POJ 2451 Uyuw’s Concert

#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<set>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define MAXN 1505

const double eps = 1e-8;
const double PI = acos(-1.0);

struct Point
{
    double x,y;
    Point() {}
    Point(double _x,double _y)
    {
        x = _x;
        y = _y;
    }
} ;

/*半平面相交(直线切割多边形)(点标号从1开始)*/
Point points[MAXN],p[MAXN],q[MAXN];
int m;
double r;
int cCnt,curCnt;
inline void getline(Point x,Point y,double &a,double &b,double &c)
{
    a = y.y - x.y;
    b = x.x - y.x;
    c = y.x * x.y - x.x * y.y;
}

inline void initial()
{
    for(int i = 1; i <= m; ++i)p[i] = points[i];
    p[m+1] = p[1];
    p[0] = p[m];
    cCnt = m;
}

inline Point intersect(Point x,Point y,double a,double b,double c)
{
    double u = fabs(a * x.x + b * x.y + c);
    double v = fabs(a * y.x + b * y.y + c);
    return Point( (x.x * v + y.x * u) / (u + v) , (x.y * v + y.y * u) / (u + v) );
}

inline void cut(double a,double b ,double c)
{
    curCnt = 0;
    for(int i = 1; i <= cCnt; ++i)
    {
        if(a*p[i].x + b*p[i].y + c >= 0) q[++curCnt] = p[i]; // 大于0 表示在直线右侧 直线顺时针行进 方向为顺时针
        else // 检查交点 交点也满足条件则加入
        {
            if(a*p[i-1].x + b*p[i-1].y + c > 0)
            {
                q[++curCnt] = intersect(p[i],p[i-1],a,b,c);
            }
            if(a*p[i+1].x + b*p[i+1].y + c > 0)
            {
                q[++curCnt] = intersect(p[i],p[i+1],a,b,c);
            }
        }
    }
    for(int i = 1; i <= curCnt; ++i) p[i] = q[i];
    p[curCnt+1] = q[1];
    p[0] = p[curCnt];
    cCnt = curCnt;
}


inline void GuiZhengHua()
{
    //规整化方向,逆时针变顺时针,顺时针变逆时针
    for(int i = 1; i < (m+1)/2; i ++)
        swap(points[i], points[m-i]);//头文件加iostream
}


double area;
inline void solve()
{
    //注意:默认点是顺时针,如果题目不是顺时针,规整化方向
    initial();
    for(int i = 1; i <= m; ++i)
    {
        double a,b,c;
        getline(points[i],points[i+1],a,b,c); // a b c 代表直线的三个系数 getline 得到 a b c
        cut(a,b,c); // 对所有点进行切割 每次更新剩余点
    }
    /*
    如果要向内推进r,用该部分代替上个函数 用于求最大内切圆 向内推进r的距离 只剩一个点则r最大
    for(int i = 1; i <= n; ++i){
        Point ta, tb, tt;
        tt.x = points[i+1].y - points[i].y;
        tt.y = points[i].x - points[i+1].x;
        double k = r / sqrt(tt.x * tt.x + tt.y * tt.y);
        tt.x = tt.x * k;
        tt.y = tt.y * k;
        ta.x = points[i].x + tt.x;
        ta.y = points[i].y + tt.y;
        tb.x = points[i+1].x + tt.x;
        tb.y = points[i+1].y + tt.y;
        double a,b,c;
        getline(ta,tb,a,b,c);
        cut(a,b,c);
    }
    */
    //多边形核的面积
    area = 0;
    for(int i = 1; i <= curCnt; ++i)
        area += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y;
    area = fabs(area / 2.0);
    //此时cCnt为最终切割得到的多边形的顶点数,p为存放顶点的数组
}

inline void init()
{
    for(int i = 1; i <= m; ++i) scanf("%lf%lf",&points[i].x,&points[i].y);
    points[m+1] = points[1];
}

int main()
{
    int ca=1;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&m);
        init();
        solve();
        printf("%.2f\n",area);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值