POJ 2451 Uyuw's Concert

本文通过POJ2451题目介绍了半平面交算法的应用,并分享了一段完整的C++实现代码。该算法用于求解由多个半平面围成的多边形区域及其面积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POJ 2451 Uyuw's Concert

半平面交第一题纪念。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<deque>
#include<queue>

using namespace std;
#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)

#define oo 1e6
#define eps 1e-6
#define nMax 100000
#define pb push_back
#define pf push_front

#define F first
#define S second

#define bug puts("OOOOh.....");
#define zero(x) (((x)>0?(x):-(x))<eps)

#define LL long long
#define DB double

int dcmp(double x){
    if(fabs(x)<eps) return 0;
    return x>0?1:-1;
}
class point {
public:
    double x,y;
    point (double x=0,double y=0):x(x),y(y) {}
    void make(double _x,double _y) {x=_x;y=_y;}
    void read() { scanf("%lf%lf",&x,&y); }
    void out() { printf("%.2lf %.2lf\n",x,y);}
    double len() { return sqrt(x*x+y*y); }
    point friend operator - (point const& u,point const& v) {
        return point(u.x-v.x,u.y-v.y);
    }
    point friend operator + (point const& u,point const& v) {
        return point(u.x+v.x,u.y+v.y);
    }
    double friend operator * (point const& u,point const& v) {
        return u.x*v.y-u.y*v.x;
    }
    double friend operator ^ (point const& u,point const& v) {
        return u.x*v.x+u.y*v.y;
    }
    point friend operator * (point const& u,double const& k) {
        return point(u.x*k,u.y*k);
    }
	friend bool operator < (point const& u,point const& v){
		if(dcmp(v.x-u.x)==0) return dcmp(u.y-v.y)<0;
		return dcmp(u.x-v.x)<0;
	}
	friend bool operator != (point const& u,point const& v){
		return dcmp(u.x-v.x) || dcmp(u.y-v.y);
	}
};
double const pi = acos(-1.0);

class HalfPlane{
	public:
	point a,b;   //vector a->b's left as a halfplane
	double arg;
	HalfPlane(){};
	HalfPlane(point a,point b):a(a),b(b) {
        arg = atan2(b.y-a.y,b.x-a.x);
        //if(dcmp(arg)<0)  2.0*pi-arg;
	}
	int contain(point );
	friend point CrossPoint(HalfPlane ,HalfPlane );
	friend bool operator < (const HalfPlane& ,const HalfPlane&);
	friend vector<point> HP_intersection(vector<HalfPlane> v);
	friend int contain(HalfPlane , point);
};
point CrossPoint(HalfPlane  u,HalfPlane v){  // The intersected point of two HalfPlanes
	point ret = u.a;
	double t = (v.a-v.b)*(u.a-v.b);
	t = t/(t-(v.a-v.b)*(u.b-v.b));
	ret = ret + (u.b-u.a)*t;
	return ret;
}
int contain(HalfPlane v,point p){
    if( dcmp((v.b-v.a)*(p-v.b))>0) return 1;
	return 0;
}
int HalfPlane::contain(point p){  // check weather point p is in HalfPlane
	if( dcmp((b-a)*(p-b))>0) return 1;          // Here ' > 'means the point on the line is not judge in HalfPlane
	return 0;
}
bool operator < (const HalfPlane& u,const HalfPlane& v){
	double ret = u.arg-v.arg;
	if(dcmp(ret)==0) {
		if(contain(v,u.a)) return 1;
		return 0;
	}
	return dcmp(ret)<0;
}
vector<point> HP_intersection(vector<HalfPlane> v){
	sort(v.begin(),v.end());
//	printf("%d\n",(int)v.size());
	deque<HalfPlane> q;
	deque<point> ans;
	while(!q.empty()) q.pop_back();
	while(!ans.empty()) ans.pop_back();
	q.pb(v[0]);
	int cnt=0;
	for(int i=1;i<(int)v.size();i++){
		if(dcmp(v[i].arg-v[i-1].arg)==0) continue;        // we only care about the HalfPlane which has diff angle.
		cnt++;
		while(ans.size()>0 && 0==v[i].contain(ans.back())) {    // check the back of the deque
			ans.pop_back();
			q.pop_back();
		}
		while(ans.size()>0 && 0==v[i].contain(ans.front())){   // check the front of deque
			ans.pop_front();
			q.pop_front();
		}
		if(q.size())
			ans.pb(CrossPoint(q.back(),v[i]));                   // add the new HalfPlane
		q.pb(v[i]);
	//	printf("%d\n",ans.size());
		//ans.back().out();
	}
	while(ans.size()>0 && 0==q.front().contain(ans.back())) {  // check the back of Point and Front of HalfPlane
		ans.pop_back();
		q.pop_back();
	}
	while(ans.size()>0 && 0==q.back().contain(ans.front())){   // check the front of Point and back of HalfPlane
		ans.pop_front();
		q.pop_front();
		//printf("%d",ans.size());
	}
	if(q.size()>=2)
		ans.pb(CrossPoint(q.front(),q.back()));                  // DO not forget the last Point
//	printf("ans = %d\n",ans.size());
	return vector<point>(ans.begin(),ans.end());
}

vector<HalfPlane> v;
vector<point> ret;
point p[nMax];
int n;

int main(){
#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
#endif
	while(~scanf("%d",&n)){
		v.clear();
		v.pb(HalfPlane(point(0,0),point(10000,0)));
		v.pb(HalfPlane(point(10000,0),point(10000,10000)));
		v.pb(HalfPlane(point(10000,10000),point(0,10000)));
		v.pb(HalfPlane(point(0,10000),point(0,0)));
		for(int i=0;i<n;i++){
			p[0].read();p[1].read();
			v.pb(HalfPlane(p[0],p[1]));
		}
		ret = HP_intersection(v);
		double ans = 0.0;
		//printf("%d\n",ret.size());
		for(int i=ret.size()-2;i>=1;i--) {
			ans += (ret[i]-ret[0])*(ret[i+1]-ret[i])*0.5;
		}
		if(dcmp(ans)<0) ans = -ans;
		printf("%.1f\n",ans );
	}
	return 0;
}


好开心。。。。

说明模板还是可行的。。。。

毕竟是手打的啊,,,,,心血啊。。。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值