! SHOI2015激光发生器




计算几何,直接模拟即可

找最近的交点然后模拟旋转

会求直线交点&向量旋转即可

注:

  1. \(acos\)值域\([0,pi]\)
  2. \(asin,atan\)值域\([-pi/2,pi/2]\)
  3. \(atan2\)值域\([-pi,pi]\)(平面直角坐标系上找点)
#include<bits/stdc++.h>
using namespace std;
struct poin{
	double x,y;
	poin(){}
	poin(double x,double y):x(x),y(y){}
	inline poin operator +(const poin &a)const{
		return poin(x+a.x,y+a.y);
	}
	inline poin operator -(const poin &a)const{
		return poin(x-a.x,y-a.y);
	}
	inline poin operator *(const double &a)const{
		return poin(x*a,y*a);
	}
	inline double operator *(const poin &a)const{
		return x*a.y-y*a.x;
	}
	inline double operator ^(const poin &a)const{
		return x*a.x+y*a.y;
	}
}; 
inline double dis(poin a){
	return sqrt(a.x*a.x+a.y*a.y);
}
inline poin rotate(poin a,double d){//clockwise
	return poin(a.x*cos(d)-a.y*sin(d),a.x*sin(d)+a.y*cos(d));
}
struct line{
	poin a,b;
	line(){}
	line(poin a,poin b):a(a),b(b){}
};
poin ins;
inline bool inters(line x,line y){
	double u=(y.b-y.a)*(x.a-y.a);
	double d=u+(x.b-y.a)*(y.b-y.a);
	ins=x.a+(x.b-x.a)*(u/d);
	if(u/d<0||u/d>1||((y.a-ins)^(y.b-y.a))>0)return 0;
	return 1;
}
const int N=104;
const double inf=1e18,eps=1e-8,pi=acos(-1.0);
poin a,b;
line s[N];
int n;
double z[N];
int main(){
	scanf("%lf%lf%lf%lf%d",&a.x,&a.y,&b.x,&b.y,&n);
	for(int i=1;i<=n;i++){
		double x,y;
		scanf("%lf%lf%lf%lf%lf%lf",&s[i].a.x,&s[i].a.y,&s[i].b.x,&s[i].b.y,&x,&y);
		z[i]=x/y;
	}
	double mn,d;
	poin u,p,v;
	for(int T=1,lst=0,id;T<=10;T++){
		id=0;mn=inf;
		for(int i=1;i<=n;i++){
			if(i==lst||fabs((s[i].b-s[i].a)*b)<eps||!inters(s[i],line(a,a+b)))continue;
			d=dis(ins-a);
			if(d<mn){id=i;mn=d;p=ins;}
		}
		if(!id){
			if(T==1)puts("NONE");
			return (0-0);
		}
		cout<<id<<" ";
		u=p-a;
		v=s[id].a-s[id].b;
		v=rotate(v,pi/2);
		if((u^v)>eps)v=rotate(v,pi);
		d=acos(-(u^v)/dis(u)/dis(v));
		a=p;
		if(u*v>0)b=rotate(b,pi-(z[id]+1)*d);
		else b=rotate(b,pi+(z[id]+1)*d);
		lst=id;
	}
	return (0-0);
}

猜你喜欢

转载自www.cnblogs.com/aurora2004/p/12566675.html