poj2318 TOYS(计算几何)

那些年不想写的计算几何,总有一天要还。
直接枚举点,枚举四边形即可,只要用叉乘判断点是否在两条线段中间即可。
O ( n m ) O(nm) O(nm)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 5010
#define eps 1e-8
inline int sgn(double x){return x<-eps?-1:x>eps;}
inline double my_sqrt(double x){if(x<eps) return 0;return sqrt(x);}
inline double sqr(double x){return x*x;}
struct point{
	double x,y;
	point(double x=0,double y=0):x(x),y(y){}
	inline double norm()const{return my_sqrt(x*x+y*y);}
	inline double norm2() const {return x*x+y*y;}
	inline point unit() const {double len=norm();return point(x/len,y/len);}
	inline point negate()const{return point(-x,-y);}
	inline point rot90() const {return point(-y,x);}//counter_clockwise
	inline point _rot90() const {return point(y,-x);}//clockwise
	inline point rotate(double theta) const {//counter_clockwise
		double c=cos(theta),s=sin(theta);
		return point(x*c-y*s,x*s+y*c);
	}
	int get(){return scanf("%lf%lf",&x,&y);}
	void out(){printf("(%.6lf,%.6lf)\n",x,y);}
};
inline bool operator==(const point &a,const point &b){
	return fabs(a.x-b.x)<=eps&&fabs(a.y-b.y)<=eps;
}
inline bool operator!=(const point &a,const point &b){
	return fabs(a.x-b.x)>eps||fabs(a.y-b.y)>eps;
}inline bool operator<(const point &a,const point &b){
	if(fabs(a.x-b.x)>eps) return a.x<b.x;
	return a.y+eps<b.y;
}
inline point operator+(const point &a,const point &b){
	return point(a.x+b.x,a.y+b.y);
}
inline point operator-(const point &a,const point &b){
	return point(a.x-b.x,a.y-b.y);
}
inline point operator*(const point &a,const double &b){
	return point(a.x*b,a.y*b);
}
inline point operator/(const point &a,const double &b){
	return point(a.x/b,a.y/b);
}
inline double det(const point &a,const point &b){
	return a.x*b.y-b.x*a.y;
}
inline double dot(const point &a,const point &b){
	return a.x*b.x+a.y*b.y;
}
inline double dis(const point &a,const point &b){
	return my_sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
struct line{
	point s,t;
	line(point s=point(),point t=point()):s(s),t(t){}
	inline double length() const {return dis(s,t);}
}li[N];
//线段交点
//注意如果两条线段是共线的且有交点,那么intersect_judgement确实会返回true
//但是line_intersect会求错,所以这种情况需要特判
inline bool point_on_segment(const point &a,const line &b){
	return sgn(det(a-b.s,b.t-b.s))==0&&dot(b.s-a,b.t-a)<eps;
}
inline bool two_side(const point &a,const point &b,const line &c){
	return sgn(det(a-c.s,c.t-c.s))*sgn(det(b-c.s,c.t-c.s))<0;
}
inline bool intersect_judgement(const line &a,const line &b){
	if(point_on_segment(b.s,a)||point_on_segment(b.t,a)) return 1;
	if(point_on_segment(a.s,b)||point_on_segment(a.t,b)) return 1;
	return two_side(a.s,a.t,b)&&two_side(b.s,b.t,a);
}
inline point line_intersect(const line &a,const line &b){
	double s1=det(a.t-a.s,b.s-a.s);
	double s2=det(a.t-a.s,b.t-a.s);
	return (b.s*s2-b.t*s1)/(s2-s1);
}
inline double point_to_line(const point &a,const line &b){
	return fabs(det(b.t-b.s,a-b.s))/dis(b.s,b.t);
}
point project_to_line(const point &a,const line &b){
	return b.s+(b.t-b.s)*(dot(a-b.s,b.t-b.s)/(b.t-b.s).norm2());
}
inline double point_to_segment(const point &a,const line &b){
	if(sgn(dot(b.s-a,b.t-b.s))*sgn(dot(b.t-a,b.t-b.s))<=0) return fabs(det(b.t-b.s,a-b.s))/dis(b.s,b.t);
	return min(dis(a,b.s),dis(a,b.t));
}
bool in_polygon(const point &p,const vector<point> &poly){
	int n=(int)poly.size();
	int counter=0;
	for(int i=0;i<n;++i){
		point a=poly[i],b=poly[(i+1)%n];
		if(point_on_segment(p,line(a,b))) return 0;//bounded excluded
		int x=sgn(det(p-a,b-a));
		int y=sgn(a.y-p.y);
		int z=sgn(b.y-p.y);
		if(x>0&&y<=0&&z>0) counter++;
		if(x<0&&z<=0&&y>0) counter--;
	}
	return counter!=0;
}
struct circle{
	point center;
	double radius;
	circle(point center=point(),double radius=0) : center(center),radius(radius) {}
};
inline bool operator==(const circle &a,const circle &b){
	return a.center==b.center&&fabs(a.radius-b.radius)<eps;
}
inline bool operator!=(const circle &a,const circle &b){
	return a.center!=b.center||fabs(a.radius-b.radius)>eps;
}
inline bool in_circle(const point &p,const circle &c){
	return dis(p,c.center)<c.radius+eps;
}
point circumcenter(const point &a,const point &b,const point &c){//三角形的外心
	point p=b-a,q=c-a,s(dot(p,p)/2,dot(q,q)/2);
	double d=det(p,q);
	return a+point(det(s,point(p.y,q.y)),det(point(p.x,q.x),s))/d;
}
//圆的生成函数
circle make_circle(const point &a,const point &b){
	return circle((a+b)/2,dis(a,b)/2);
}
circle make_circle(const point &a,const point &b,const point &c){
	point center=circumcenter(a,b,c);
	return circle(center,dis(center,a));
}
//直线与圆的交点
//返回ab方向的第一个交点
point line_circle_intersect(const line &l,const circle &c){
	double x=my_sqrt(sqr(c.radius)-sqr(point_to_line(c.center,l)));
	return project_to_line(c.center,l)+(l.s-l.t).unit()*x;
}
//圆与圆的交点
point circle_intersect(const circle &a,const circle &b){//get another point using circle_intersect(b,a)
	point r=(b.center-a.center).unit();
	double d=dis(a.center,b.center);
	double x=.5*((sqr(a.radius)-sqr(b.radius))/d+d);
	double h=my_sqrt(sqr(a.radius)-sqr(x));
	return a.center+r*x+r.rot90()*h;
}
//点到圆的切线
pair<line,line> tangent(const point &p,const circle &c){
	circle a=make_circle(p,c.center);
	return make_pair(circle_intersect(a,c),circle_intersect(c,a));
}
int n,m,ans[N];
inline bool check(const point &p,const line &a,const line &b){
	return sgn(det(p-a.s,a.t-a.s))*sgn(det(p-b.s,b.t-b.s))<=0;
}
int main(){
//	freopen("a.in","r",stdin);
	while(1){
		scanf("%d",&n);
		if(!n) break;
		int x1,y1,x2,y2;
		memset(ans,0,sizeof(ans));
		scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
		li[0]=line(point(x1,y2),point(x1,y1));
		li[n+1]=line(point(x2,y2),point(x2,y1));
		for(int i=1;i<=n;++i){
			int x3,x4;scanf("%d%d",&x3,&x4);
			li[i]=line(point(x4,y2),point(x3,y1));
		}
		while(m--){
			int x,y;scanf("%d%d",&x,&y);
			if(x==x1){ans[0]++;continue;}
			if(x==x2){ans[n]++;continue;}
			for(int i=0;i<=n;++i){
				if(check(point(x,y),li[i],li[i+1])){
					ans[i]++;break;
				}
			}
		}
		for(int i=0;i<=n;++i) printf("%d: %d\n",i,ans[i]);
		puts("");
	}
	return 0;
}                                                           
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值