题解 P4361 【[SHOI2015]激光发生器】
这里给出向量旋转公式的推导过程。
所以向量
对于本题则直接模拟光线的反射过程即可。
#include<cstdio>
#include<cctype>
#include<cmath>
using namespace std;
//#define getchar() (SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1 << 15],*SS = BB,*TT = BB;
using namespace std;
inline int read()
{
int x = 0,f = 1;
char ch = getchar();
for(;!isdigit(ch);ch = getchar())
if(ch == '-')
f = -1;
for(;isdigit(ch);ch = getchar())
x = x * 10 + (ch ^ 48);
return x * f;
}
void print(long long x)
{
if(x < 0)
putchar('-'),x = -x;
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
const double eps = 1e-9,pi = acos(-1);
int dcmp(double x)
{
if(fabs(x) < eps)
return 0;
return x < 0 ? -1 : 1;
}
struct point
{
double x,y;
void read()
{
x = ::read(),y = ::read();
}
point(double _x = 0,double _y = 0)
{
x = _x,y = _y;
}
friend point operator + (point szq,point yqy)
{
return point(szq.x + yqy.x,szq.y + yqy.y);
}
friend point operator - (point szq,point yqy)
{
return point(szq.x - yqy.x,szq.y - yqy.y);
}
friend point operator * (point szq,double yqy)
{
return point(szq.x * yqy,szq.y * yqy);
}
friend double operator * (point szq,point yqy)
{
return szq.x * yqy.x + szq.y * yqy.y;
}
friend double operator & (point szq,point yqy)
{
return szq.x * yqy.y - szq.y * yqy.x;
}
void rotate(double rad)
{
*this = point(x * cos(rad) - y * sin(rad),x * sin(rad) + y * cos(rad));
}
double lenth()
{
return sqrt((*this) * (*this));
}
bool onSeg(point szq,point yqy)
{
return dcmp((szq - *this) & (yqy - *this)) == 0 && dcmp((szq - *this) * (yqy - *this)) < 0;
}
};
point intersection(point p,point v,point q,point w)
{
return p + v * ((w & (p - q)) / (v & w));
}
double angle(point a,point b)
{
return acos(a * b / a.lenth() / b.lenth());
}
const int N = 110;
int n;
struct Mirror
{
point s,t;
double a,b;
}a[N];
point p,d;
int main()
{
p.read(),d.read();n = read();
for(int i = 1;i <= n;i++)
a[i].s.read(),a[i].t.read(),a[i].a = read(),a[i].b = read();
bool fl = false;
for(int T = 1;T <= 10;T++)
{
double minn = 1e200;
int id = -1;
for(int i = 1;i <= n;i++)
{
point v = a[i].t - a[i].s;
if(dcmp(v & d))
{
point t = intersection(a[i].s,v,p,d);
if(t.onSeg(a[i].s,a[i].t) && dcmp(d * (t - p)) > 0)
{
double dis = (t - p).lenth();
if(dis < minn)
minn = dis,id = i;
}
}
}
if(!~id)
break;
point v = a[id].t - a[id].s;
p = intersection(a[id].s,v,p,d);
print(id),putchar(' ');
fl = true;
if(!dcmp(v * d))
{
d = d * -1;
continue;
}
if(dcmp(d * v) < 0)
v = v * -1;
double alpha = pi / 2 - angle(v,d);
alpha = pi / 2 - alpha * a[id].a / a[id].b;
int bt = dcmp(d & v);
v.rotate(bt * alpha);
d = v;
}
if(!fl)
puts("NONE");
}