LP4196 [CQOI2006] 凸多边形

emm

Half Plane Intersection

建议背就完事了...

这里说几点:

  • 先退队尾再退队首。
  • 记得判下队列无解。
  • 不要使用线段交点。请使用直线交点。且注意向量的方向。其中用到了正弦定理。

Code

// Code by ajcxsu
// Problem: half

#define _USE_MATH_DEFINES
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#define eps (1e-8)
using namespace std;

const int N=2e4+10;
double rbq(double x, double y) { return fabs(x-y)<eps; }
struct P {
    double x, y, d;
    P () { x=y=d=0; }
    P (double a, double b) { x=a, y=b, d=atan2(y, x); if(d<0) d+=2.0*M_PI; }
    P operator + (P b) { return P(x+b.x, y+b.y); }
    P operator - (P b) { return P(x-b.x, y-b.y); }
    P operator * (double b) { return P(x*b, y*b); }
    double operator ^ (P b) { return x*b.y-y*b.x; }
    double norm() { return x*x+y*y; }
    double dis() { return sqrt(norm()); }
    bool operator < (const P &b) const { return d<b.d; }
    bool operator == (const P &b) const { return rbq(d, b.d); }
    bool operator != (const P &b) const { return !rbq(d, b.d); }
} ;
struct Seg {
    P s, e, b;
    Seg () { s=e=b=P(); }
    Seg (P x, P y) { s=x, e=y, b=e-s; }
} s[N], rs[N];
double side(P x, Seg s) { return s.b^(x-s.s); }
bool cmp(const Seg &a, const Seg &b) { return a.b==b.b?side(a.s, b)>0:a.b<b.b; }

double S(P a, P b) { return fabs(a^b); }

P ins(Seg a,Seg b) {
    P p1=a.s,p2=b.s,v1=a.e,v2=b.e;
    v1=v1-p1;v2=v2-p2;
    P u=p2-p1;
    P p=p2+v2*((u^v1)/(v1^v2));
    return p;
}

istream& operator >> (istream &in, P &x) {
    double a, b; in>>a>>b, x=P(a, b);
    return in;
}
ostream& operator << (ostream &out, P x) {
    return out<<x.x<<' '<<x.y;
}

int sn;
Seg qu[N]; int h, t;
double HPI() {
    int n=sn;
    sort(s+1, s+1+n, cmp);
    int p=0; rs[++p]=s[1];
    for(int i=2; i<=n; i++) if(s[i].b!=s[i-1].b)
        rs[++p]=s[i];
    qu[t++]=rs[1], qu[t++]=rs[2];
    for(int i=3; i<=p; i++) {
        while(h+1<t && side(ins(qu[t-1], qu[t-2]), rs[i])<0) t--;
        while(h+1<t && side(ins(qu[h], qu[h+1]), rs[i])<0) h++;
        qu[t++]=rs[i];
    }
    while(h+1<t && side(ins(qu[t-1], qu[t-2]), qu[h])<0) t--;
    while(h+1<t && side(ins(qu[h], qu[h+1]), qu[t-1])<0) h++;
    if(t-h<=1) return 0;
    vector<P> tmp;
    for(int j=h; j<t-1; j++)
        tmp.push_back(ins(qu[j], qu[j+1]));
    tmp.push_back(ins(qu[t-1], qu[h]));
    double area=0;
    for(int i=0, len=tmp.size(); i<len-1; i++) area+=tmp[i]^tmp[i+1];
    area+=tmp.back()^tmp.front();
    return fabs(area)/2.0;
}

P tmp[100];
int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.setf(ios::fixed), cout<<setprecision(3);
    int n; cin>>n;
    for(int i=0; i<n; i++) {
        int k; cin>>k;
        for(int j=0; j<k; j++) cin>>tmp[j];
        for(int j=0; j<k-1; j++) s[++sn]=Seg(tmp[j],tmp[j+1]);
        s[++sn]=Seg(tmp[k-1],tmp[0]);
    }
    cout<<HPI()<<endl;
    return 0;
}

本文链接:https://acxblog.site/archives/half-plane-intersection.html
文章采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。