有人帮帮我的半平面交吗
  • 板块学术版
  • 楼主JoshAlMan
  • 当前回复7
  • 已保存回复7
  • 发布时间2022/7/23 17:28
  • 上次更新2023/10/27 18:45:11
查看原帖
有人帮帮我的半平面交吗
161687
JoshAlMan楼主2022/7/23 17:28

已经查了2h了,过不去poj2451.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define x first
#define y second
using namespace std;

typedef pair<double, double> PDD;

const int N = 2e4 + 5;

const double eps = 1e-10;

int n, tot, q[N];

PDD p[N];

struct Line{
    PDD s, t;
    int id;
} e[N];

double inline dot(PDD a, PDD b) { return a.x * b.x + a.y * b.y; }
double inline getAngle(Line a) { return atan2(a.t.y - a.s.y, a.t.x - a.s.x); }
PDD operator - (const PDD &a, const PDD &b) { return make_pair(a.x - b.x, a.y - b.y); }
double cross(PDD a, PDD b) { return a.x * b.y - a.y * b.x; }
double area(PDD a, PDD b, PDD c) { return cross(b - a, c - a); }

int inline sig(double x) {
    if (fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}

bool cmp (const Line &a, const Line &b) {
    double A = getAngle(a), B = getAngle(b);
    if (sig(A - B) < 0) return A < B;
    else return area(a.s, a.t, b.t) < 0;
}

PDD getInter(PDD p, PDD v, PDD q, PDD w) {
    PDD u = p - q;
    double t = cross(w, u) / cross(v, w);
    return make_pair(p.x + t * v.x, p.y + t * v.y);
}

PDD getInter(Line a, Line b) { return getInter(a.s, a.t - a.s, b.s, b.t - b.s); }

bool inline Right(Line a, Line b, Line c) {
    PDD u = getInter(b, c);
    return sig(area(a.s, a.t, u)) < 0;
}

double HPI() {
    sort(e + 1, e + 1 + n, cmp);
    int hh = 0, tt = -1;
    for (int i = 1; i <= n; i++) {
        if (i > 1 && sig(getAngle(e[i]) - getAngle(e[i - 1])) == 0) continue;
        while (hh < tt && Right(e[i], e[q[tt - 1]], e[q[tt]])) tt--;
        while (hh < tt && Right(e[i], e[q[hh]], e[q[hh + 1]])) hh++;
        q[++tt] = i;
    }
    while (hh < tt && Right(e[q[hh]], e[q[tt - 1]], e[q[tt]])) tt--;
    while (hh < tt && Right(e[q[tt]], e[q[hh]], e[q[hh + 1]])) hh++;
    if (tt - hh + 1 < 3) return 0;
	q[++tt] = q[hh];
    tot = 0;
    for (int i = hh; i < tt; i++)
        p[++tot] = getInter(e[q[i]], e[q[i + 1]]);
    double res = 0;
    for (int i = 1; i < tot; i++)
        res += area(p[1], p[i], p[i + 1]);
    return fabs() / 2;
}

#define mp make_pair



int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
    	cin >> e[i].s.x >> e[i].s.y;
    	cin >> e[i].t.x >> e[i].t.y;
	}
	e[++n] = (Line) { mp(0, 0), mp(10000, 0)} ;
	e[++n] = (Line) { mp(10000, 0), mp(10000, 10000)} ;
	e[++n] = (Line) { mp(10000, 10000), mp(0, 10000)} ;
	e[++n] = (Line) { mp(0, 10000), mp(0, 0)} ;
	
	printf("%.1lf\n", HPI());
}

网上随便找一个逻辑完全一样的对的:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define eps 1e-10
using namespace std;
double area;
int n,top,bot,tot;
struct P{double x,y;}a[20005];
struct L{P a,b;double angle;}l[20005],q[20005];
P operator-(P a,P b)
{
	P t;t.x=a.x-b.x;t.y=a.y-b.y;return t;
}
double operator*(P a,P b)
{
	return a.x*b.y-a.y*b.x;
}
bool operator<(L a,L b)
{
	if(a.angle==b.angle)
		return (b.b-a.a)*(b.a-a.a)>0;
	return a.angle<b.angle;
}
P inter(L a,L b)
{
	double k1,k2,t;
	k1=(a.b-b.a)*(b.b-b.a);
	k2=(b.b-b.a)*(a.a-b.a);
	t=k1/(k1+k2);
	P ans;
	ans.x=a.b.x+(a.a.x-a.b.x)*t;
	ans.y=a.b.y+(a.a.y-a.b.y)*t;
	return ans;
}
bool jud(L a,L b,L t)
{
	P p=inter(a,b);
	return (t.a-p)*(t.b-p)<0;
}
void hpi()
{
	sort(l+1,l+n+1);
	int top=1,bot=0;
	for(int i=1;i<=n;i++)
	{
		if(l[i].angle!=l[i-1].angle)tot++;
		l[tot]=l[i];
	}
	n=tot;q[0]=l[1];q[1]=l[2];
	for(int i=3;i<=n;i++)
	{
		while(bot<top&&jud(q[top],q[top-1],l[i]))top--;
		while(bot<top&&jud(q[bot],q[bot+1],l[i]))bot++;
		q[++top]=l[i];
	}
	while(bot<top&&jud(q[top],q[top-1],q[bot]))top--;
	while(bot<top&&jud(q[bot],q[bot+1],q[top]))bot++;
	q[top+1]=q[bot];
	tot=0;
	for(int i=bot;i<=top;i++)
		a[++tot]=inter(q[i],q[i+1]);
}
void getarea()
{
	if(tot<3)return;
	a[++tot]=a[1];
	for(int i=1;i<=tot;i++)
		area+=a[i]*a[i+1];
	area=fabs(area)/2;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y);
	}
	l[++n].a.x=0;l[n].a.y=0;l[n].b.x=10000;l[n].b.y=0;
	l[++n].a.x=10000;l[n].a.y=0;l[n].b.x=10000;l[n].b.y=10000;
	l[++n].a.x=10000;l[n].a.y=10000;l[n].b.x=0;l[n].b.y=10000;
	l[++n].a.x=0;l[n].a.y=10000;l[n].b.x=0;l[n].b.y=0;
	for(int i=1;i<=n;i++)
		l[i].angle=atan2((l[i].b.y-l[i].a.y),(l[i].b.x-l[i].a.x));
	hpi();
	getarea();
	printf("%.1lf",area);
	return 0;
}
2022/7/23 17:28
加载中...