社区讨论
求助半平面交,洛谷过了但是POJ2451挂了
学术版参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo21eg4u
- 此快照首次捕获于
- 2023/10/23 06:25 2 年前
- 此快照最后确认于
- 2023/11/03 06:47 2 年前
想知道代码是有什么没考虑到的地方吗,求指出不足的写法
CPP//#include<bits/stdc++.h>
#include<vector>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<map>
#include<queue>
#define int long long
#define inf (int)1e18
#define N 300007
#define M 200007
#define mod 1000000007
#define P pair<int,int>
#define MP(a,b) make_pair(a,b)
#define V vector<int>
#define VP vector<pair<int,int>>
#define PI (double)3.1415926535
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
inline int R()
{
char ch=getchar();bool f=0;int x=0;
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=1;
for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
if(f==1)x=-x;return x;
}
int T=1,n,m;
//---------------------------------------------------------------点和向量部分
struct Point
{
double x,y;
Point(double xx=0,double yy=0){x=xx,y=yy;};
};
typedef Point Vector;//向量和点类似
Vector operator + (Vector a,Vector b){return (Vector){a.x+b.x,a.y+b.y};}//向量加
Vector operator - (Vector a,Vector b){return (Vector){a.x-b.x,a.y-b.y};}//向量减
Vector operator * (Vector a,double b){return (Vector){a.x*b,a.y*b};}//数乘
Vector operator / (Vector a,double b){return (Vector){a.x/b,a.y/b};}
double Dot(Vector a,Vector b) {return a.x*b.x+a.y*b.y;}//点积
double Len(Vector a) {return sqrt(Dot(a,a));}//向量的长度等于sqrt(x^2+y^2)
double Angle(Vector a,Vector b) {return acos(Dot(a,b)/Len(a)/Len(b));}//向量的夹角等于acos(a·b/|a|/|b|)
Vector Rotate(Vector a,double rad) {return (Vector){a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad)};}//将向量a逆时针旋转rad度
double Cross(Vector a,Vector b) {return a.x*b.y-a.y*b.x;}//平面叉积姑且定为一个数,大小表示平行四边形面积
Vector Normal(Vector a) {double len=Len(a);return (Vector){-a.y/len,a.x/len};}//求向量a的单位法向量
double Out(double a){if(fabs(a)<1e-9) a=0;return a;};//避免输出-0.000
//---------------------------------------------------------------直线部分
struct Line//一个结构体用来存储一条直线
{
Point a,b;//存储直线上两点坐标,两点确定一条直线
Line(Point x=Point(0,0),Point y=Point(0,0)):a(x),b(y){}
};
typedef Line Segment;//线段在代码中其实与直线差不多,因此可以直接typedef一下
double PtoL(Point A,Line L) {return fabs(Cross(A-L.a,L.a-L.b))/Len(L.a-L.b);}//点到直线的距离
double PtoS(Point A,Segment S)//点到线段的距离
{
if(Dot(A-S.a,S.b-S.a)<0) return Len(A-S.a);//如果垂直点不在线段上,且点A离线段的A端点较近
if(Dot(A-S.b,S.a-S.b)<0) return Len(A-S.b);//如果垂直点不在线段上,且点A离线段的B端点较近
return PtoL(A,S);//如果垂直点在线段上,直接按求点到直线上的距离做即可
}
bool IsIntersect(Segment S1,Segment S2)//判断两条线段是否相交,1为相交 (端点有问题)
{
double f1=Cross(S1.b-S1.a,S2.a-S1.a),f2=Cross(S1.b-S1.a,S2.b-S1.a);//判断第一条线段的两端是否在第二条线段两端
double g1=Cross(S2.b-S2.a,S1.a-S2.a),g2=Cross(S2.b-S2.a,S1.b-S2.a);//判断第二条线段的两端是否在第一条线段两端
return ((f1<0)^(f2<0))&&((g1<0)^(g2<0));
}
Point LineIntersection(Line L1,Line L2) {return L1.a+(L1.b-L1.a)*Cross(L2.b-L2.a,L1.a-L2.a)/Cross(L1.b-L1.a,L2.b-L2.a);}//求两直线交点
//---------------------------------------------------------------多边形部分
struct Polygon//一个结构体用来存储一个多边形
{
int n;Point p[20005];//n存储点数,P数组存储点
Polygon() {n=0;}//构造函数
};
#define eps 1e-10//设置eps减小精度误差
int Dcmp(double x) {return fabs(x)<eps?0:(x>0?1:-1);}//判断正负
int IsInPolygon(Point A,Polygon Pol)//判断一个点是否在多边形内部(待验证)
{
int flag=0,k,d1,d2;
for(int i=1;i<=Pol.n;++i)//枚举边
{
if(!Dcmp(PtoS(A,Segment(Pol.p[i],Pol.p[i%Pol.n+1])))) return -1;//如果点在边上,返回-1
k=Dcmp(Cross(Pol.p[i%Pol.n+1]-Pol.p[i],A-Pol.p[i])),d1=Dcmp(Pol.p[i].y-A.y),d2=Dcmp(Pol.p[i%Pol.n+1].y-A.y),
k>0&&d1<=0&&d2>0&&++flag,k<0&&d1>0&&d2<=0&&--flag;//更新flag
}
return flag?1:0;//flag>0表示在多边形内部,否则说明在多边形外部
}
double PolygonArea(Polygon Pol)//求多边形面积
{
double res=0;//res统计和
for(int i=2;i<Pol.n;++i) res+=Cross(Pol.p[i]-Pol.p[1],Pol.p[i+1]-Pol.p[1])/2;//计算由1号节点,i号节点,i+1号节点构成的三角形面积
return res;//返回答案
}
Line li[N];
int lcnt;
Polygon pol;
bool Cmp(Line x,Line y)
{
double ang1=atan2((x.b-x.a).y,(x.b-x.a).x),ang2=atan2((y.b-y.a).y,(y.b-y.a).x);
if(fabs(ang1-ang2)<eps)
return Cross(x.b-x.a,y.b-x.a)<0;
return ang1<ang2;
}
int que[N];
bool Check(Line x,Line y,Line z)
{
Point c=LineIntersection(y,z);
double now=Cross(x.b-x.a,c-x.a);
if(now<0)
return 1;
return 0;
}
bool Solve()
{
n=R();
for(int i=1;i<=n;++i)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
li[++lcnt]=(Line){(Point){x1,y1},(Point){x2,y2}};
}
li[++lcnt]=(Line){(Point){0,0},(Point){10000,0}};
li[++lcnt]=(Line){(Point){10000,0},(Point){10000,10000}};
li[++lcnt]=(Line){(Point){10000,10000},(Point){0,10000}};
li[++lcnt]=(Line){(Point){0,10000},(Point){0,0}};
sort(li+1,li+1+lcnt,Cmp);
int l=1,r=1;
que[r]=1;
for(int i=2;i<=lcnt;++i)
{
double ang1=atan2((li[i].b-li[i].a).y,(li[i].b-li[i].a).x),ang2=atan2((li[i-1].b-li[i-1].a).y,(li[i-1].b-li[i-1].a).x);
if(fabs(ang1-ang2)<eps)
continue;
while(r-l>=1&&Check(li[i],li[que[r]],li[que[r-1]]))--r;
while(r-l>=1&&Check(li[i],li[que[l]],li[que[l+1]]))++l;
que[++r]=i;
}
while(r-l>=1&&Check(li[que[l]],li[que[r]],li[que[r-1]])) --r;
for(int i=l;i<=r;++i)
{
if(i==r)
pol.p[++pol.n]=LineIntersection(li[que[r]],li[que[l]]);
else
pol.p[++pol.n]=LineIntersection(li[que[i]],li[que[i+1]]);
}
printf("%.1lf\n",PolygonArea(pol));
return true;
}
signed main()
{
//T=R();
while(T--)
if(!Solve())
printf("-1\n");
return 0;
}
/*
-std=c++11
-std=c99
*/
回复
共 1 条回复,欢迎继续交流。
正在加载回复...