POJ - 2451 Uyuw's Concert(半平面交求核面積)

鏈接:https://cn.vjudge.net/problem/POJ-2451

題意:半平面交求核面積。

思路:板子題,也是存板子。兩個板子,思想一樣,實現略微不同。

1.

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const double eps = 1e-5;
const int N = 2e4+10; 
const double maxx=1e4;
int sgn(double x)
{
	if(fabs(x)<eps) return 0;
	else if(x<0) return -1;
	else return 1;
}
struct Point
{
	double x,y;
	Point(){}
	Point(double x,double y):x(x),y(y){}
	Point operator -(const Point& b)const//相減 
	{
		return Point(x-b.x,y-b.y);
	}
	double operator ^(const Point& b)const//叉乘 
	{
		return x*b.y-y*b.x;
	}
	double operator *(const Point& b)const//點乘 
	{
		return x*b.x+y*b.y;
	}
};
struct Line
{
	Point s,e;
	double A;
	Line(){}
	Line(Point ss,Point ee)
	{
		s=ss,e=ee;
	}
	void getangle()//獲得極角 
	{
		A=atan2(e.y-s.y,e.x-s.x);
	}
	pair<Point,int> operator &(const Line& b)const//兩直線相對關係 
	{
		Point res=s;
		if(sgn((s-e)^(b.s-b.e))==0)
		{
			if(sgn((b.s-s)^(b.e-s))==0)//兩直線重合 
				return make_pair(res,0);
			else return make_pair(res,1);//兩直線平行 
		}
		double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
		res.x+=(e.x-s.x)*t;
		res.y+=(e.y-s.y)*t;
		return make_pair(res,2);//兩直線相交 
	}
};
Point p[N],ps[N],qu[N];
Line ls[N],q[N];
double x;
int n;
double dis(Point a,Point b)
{
	return sqrt((a-b)*(a-b));
}
bool hpicmp(Line a,Line b)
{
	if(sgn(a.A-b.A)!=0)	
		return a.A<b.A;	
	else return sgn((a.s-b.s)^(b.e-b.s))<0;
}
bool onright(Line l1,Line l2,Line l3)
{
	Point p=(l1&l2).first;
	x=((l3.e-l3.s)^(p-l3.s));
	if(sgn(x)<0) return 1;
	else return 0;
}
double getarea(Point p[],int n)
{
	double ans=0;
	for(int i=1;i<n-1;i++)
		ans+=((p[i]-p[0])^(p[i+1]-p[0]));
	return fabs(ans)/2.0;
}
double hpi()
{
	int he=0,ta=1,cnt=0;
    sort(ls,ls+n,hpicmp);
    cnt=1;
    for(int i=1;i<n;i++)
        if(sgn(ls[i].A-ls[i-1].A)>0)
        	ls[cnt++]=ls[i];
    q[0]=ls[0];
    q[1]=ls[1];
	for(int i=2;i<cnt;i++)
	{
		/*if(he<ta&&sgn((q[ta].e-q[ta].s)^(q[ta-1].e-q[ta-1].s))==0
		||sgn((q[he].e-q[he].s)^(q[he+1].e-q[he+1].s))==0)
			return 0;*/
		while(he<ta&&onright(q[ta-1],q[ta],ls[i])) ta--;
		while(he<ta&&onright(q[he],q[he+1],ls[i])) he++;
		q[++ta]=ls[i];
	}
	while(he<ta&&onright(q[ta-1],q[ta],q[he])) ta--;
	while(he<ta&&onright(q[he],q[he+1],q[ta-1])) he++;
	if(he+1>=ta) return 0;
	cnt=0;
	for(int i=he;i<ta;i++)
		p[cnt++]=(q[i]&q[i+1]).first;
	p[cnt++]=(q[he]&q[ta]).first;
	return getarea(p,cnt);
}
int main(void)
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%lf%lf",&ls[i].s.x,&ls[i].s.y);
		scanf("%lf%lf",&ls[i].e.x,&ls[i].e.y);	
		ls[i].getangle();		
	} 
	ls[n++]=Line(Point(0,0),Point(maxx,0));
	ls[n-1].getangle();
	ls[n++]=Line(Point(maxx,0),Point(maxx,maxx));
	ls[n-1].getangle();
	ls[n++]=Line(Point(maxx,maxx),Point(0,maxx));
	ls[n-1].getangle();
	ls[n++]=Line(Point(0,maxx),Point(0,0));	
	ls[n-1].getangle();		
	printf("%.1f\n",hpi()); 	
	return 0;
}

2.

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const double eps = 1e-5;
const double maxx = 1e4;
const int N = 2e4+10; 
int sgn(double x)
{
	if(fabs(x)<eps) return 0;
	else if(x<0) return -1;
	else return 1;
}
 
struct Point
{
	double x,y;
	Point(){}
	Point(double x,double y):x(x),y(y){}
	Point operator -(const Point& b)const//相減 
	{
		return Point(x-b.x,y-b.y);
	}
	double operator ^(const Point& b)const//叉乘 
	{
		return x*b.y-y*b.x;
	}
	double operator *(const Point& b)const//點乘 
	{
		return x*b.x+y*b.y;
	}
};
struct Line
{
	Point s,e;
	Line(){}
	Line(Point ss,Point ee)
	{
		s=ss,e=ee;
	}
	pair<Point,int> operator &(const Line& b)const//兩直線相對關係 
	{
		Point res=s;
		if(sgn((s-e)^(b.s-b.e))==0)
		{
			if(sgn((b.s-s)^(b.e-s))==0)//兩直線重合 
				return make_pair(res,0);
			else return make_pair(res,1);//兩直線平行 
		}
		double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
		res.x+=(e.x-s.x)*t;
		res.y+=(e.y-s.y)*t;
		return make_pair(res,2);//兩直線相交 
	}
};
Point ps[N];
Line ls[N],q[N];
double x;
int n;
double dis(Point a,Point b)
{
	return sqrt((a-b)*(a-b));
}
double getA(Line a)
{
	return atan2(a.e.y-a.s.y,a.e.x-a.s.x);
}
bool cmp(Line a,Line b)
{
	double A=getA(a),B=getA(b);
	if(sgn(A-B)==0)	
		return ((a.e-a.s)^(b.e-a.s))>=0;
	else return A<B;
}
bool del(Line l1,Line l2,Line l3)
{
	Point p=(l1&l2).first;
	x=((l3.e-l3.s)^(p-l3.s));
	if(sgn(x)<0) return 1;
	else return 0;
}
double getarea(Point p[],int n)
{
	double ans=0;
	for(int i=1;i<n-1;i++)
		ans+=((p[i]-p[0])^(p[i+1]-p[0]));
	return fabs(ans)/2.0;
}
double hpi()
{
	int he=0,ta=0,cnt=0;
	sort(ls,ls+n,cmp);   
	for(int i=0;i<n-1;i++)
	{
		if(sgn(getA(ls[i])-getA(ls[i+1]))==0)
			continue;
		ls[cnt++]=ls[i];
	}
	ls[cnt++]=ls[n-1];
	for(int i=0;i<cnt;i++)
	{
		while(ta-he>1&&del(q[ta-2],q[ta-1],ls[i])) ta--;
		while(ta-he>1&&del(q[he],q[he+1],ls[i])) he++;
		q[ta++]=ls[i];
	}
	while(ta-he>1&&del(q[ta-2],q[ta-1],q[he])) ta--;
	while(ta-he>1&&del(q[he],q[he+1],q[ta-1])) he++;
	if(ta-he<=2) return 0;
	else 
	{
		cnt=0;
		for(int i=he;i+1<ta;i++)
			ps[cnt++]=(q[i]&q[i+1]).first;
		ps[cnt++]=(q[he]&q[ta-1]).first;
		return getarea(ps,cnt);	
	}  
}
bool judge() 
{
  double ans=0;
  for (int i=1;i<n-1;i++) 
    ans+=((ps[i]-ps[0])^(ps[i+1]-ps[0]));
  return ans<0;
}
int main(void)
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%lf%lf",&ls[i].s.x,&ls[i].s.y);
		scanf("%lf%lf",&ls[i].e.x,&ls[i].e.y);		
	} 
	ls[n++]=Line(Point(0,0),Point(maxx,0));
	ls[n++]=Line(Point(maxx,0),Point(maxx,maxx));
	ls[n++]=Line(Point(maxx,maxx),Point(0,maxx));
	ls[n++]=Line(Point(0,maxx),Point(0,0));	;		
	printf("%.1f\n",hpi()); 	
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章