• bzoj 4595 激光发生器


    bzoj 4595 激光发生器

    • 光线为射线,每次找到与当前光线相交且距离最近的镜子,然后旋转光线.
    • 直线,射线利用线上一点+方向向量的方式表示.旋转时,旋转中心作为线上一点不变,方向向量左乘旋转矩阵.
    • 即逆时针转过 ( heta) 角,方向向量 ((x,y)) 变为 ((cos heta cdot x-sin heta cdot y,sin hetacdot x+cos hetacdot y)).
    • 实现时特判较多,需注意细节.
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mp make_pair
    #define pii pair<int,int>
    inline int read()
    {
    	int x=0;
    	bool pos=1;
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())
    		if(ch=='-')
    			pos=0;
    	for(;isdigit(ch);ch=getchar())
    		x=x*10+ch-'0';
    	return pos?x:-x;
    }
    const int MAXN=110;
    const double eps=1e-8;
    int dcmp(double x)
    {
    	return fabs(x)<=eps?0:(x>0?1:-1);
    }
    struct v2{
    	double x,y;
    	v2(double x=0,double y=0):x(x),y(y) {}
    	v2 operator + (const v2 &rhs) const
    		{
    			return v2(x+rhs.x,y+rhs.y);
    		}
    	v2 operator / (const double &rhs) const
    		{
    			return v2(x/rhs,y/rhs);
    		}
    	v2 operator - (const v2 &rhs) const
    		{
    			return v2(x-rhs.x,y-rhs.y);
    		}
    	double operator * (const v2 &rhs) const
    		{
    			return x*rhs.y-y*rhs.x;
    		}
    	double modulus()
    		{
    			return sqrt(x*x+y*y);
    		}
    };
    #define point v2
    #define vector v2
    v2 rotate(v2 v,double rad)
    {
    	return v2(v.x*cos(rad)-v.y*sin(rad),v.x*sin(rad)+v.y*cos(rad));
    }
    v2 inter(point p,vector v,point q,vector w)
    {
    	v2 u=p-q;
    	double t=(w*u)/(v*w);
    	return p+v2(v.x*t,v.y*t);
    }
    double dot(v2 a,v2 b)
    {
    	return a.x*b.x+a.y*b.y;
    }
    bool onseg(point p,point a1,point a2)
    {
    	return dcmp((a1-p)*(a2-p))==0 && dcmp(dot(a1-p,a2-p))<0; 
    }
    double angle(v2 a,v2 b)
    {
    	return acos(fabs(dot(a,b)/a.modulus()/b.modulus()-eps));
    }
    struct mir{
    	v2 p1,p2;
    	double a,b;
    }a[MAXN];
    double x,y,dx,dy;
    int n;
    int main()
    {
    	int cnt=0;
    	scanf("%lf%lf%lf%lf",&x,&y,&dx,&dy);
    	n=read();
    	for(int i=1;i<=n;++i)
    		scanf("%lf%lf%lf%lf%lf%lf",&a[i].p1.x,&a[i].p1.y,&a[i].p2.x,&a[i].p2.y,&a[i].a,&a[i].b);
    	point p(x,y);
    	vector v(dx,dy);
    	for(int T=1;T<=10;++T)
    		{
    			double mdis=1e100;
    			int id=0;
    			for(int i=1;i<=n;++i)
    				{
    					if(dcmp((a[i].p1-a[i].p2)*v)!=0)
    						{
    							point t=inter(a[i].p1,a[i].p2-a[i].p1,p,v);
    							if(onseg(t,a[i].p1,a[i].p2) && dcmp(dot(v,t-p))>0)
    								{
    									double dis=(p-t).modulus();
    									if(dis<mdis)
    										mdis=dis,id=i;
    								}
    						}
    				}
    			if(id==0)
    				break;
    			++cnt;
    			p=inter(a[id].p1,a[id].p2-a[id].p1,p,v);
    			if(dcmp(dot(a[id].p1-a[id].p2,v)==0))
    				v=v2(-v.x,-v.y);
    			else
    				{
    					vector t=a[id].p2-a[id].p1;
    					if(dcmp(dot(a[id].p1-a[id].p2,v)>0))
    						t=t/(-1);
    					double alpha=acos(-1)/2-angle(t,v);
    					int bt=dcmp(t*v);
    					v=rotate(t,bt*(alpha*a[id].a/a[id].b-acos(-1)/2));
    				}
    			printf("%d ",id);
    		}
    	if(!cnt)
    		puts("NONE");
    	return 0;
    }
    
    
  • 相关阅读:
    Linux网络与服务管理
    输入两个数据,如果输入数据之和为5的倍数,那么就算是输了,停止游戏;如果赢了,接着输入数据。
    switch语句
    计算一个三位数的个位,十位,百位之和
    单分支和双分支选择结构程序设计
    register变量
    static变量
    auto变量
    长双精度类型
    双精度类型变量
  • 原文地址:https://www.cnblogs.com/jklover/p/10388852.html
Copyright © 2020-2023  润新知