题解
我永远都写不对计算几何……
首先找到反射的线段比较好找,扫一遍所有线段然后找交点在镜子上并且交点离起点最近的那条线段
然后旋转的时候,有可能是顺时针,也有可能是逆时针,要找出法线,然后判断法线和光线的角度然后确定顺时针逆时针
代码
#include <bits/stdc++.h>
#define enter putchar('
')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 200005
#define pb push_back
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
bool dcmp(db a,db b) {
return fabs(a - b) < eps;
}
struct Point {
db x,y;
Point(){}
Point(db _x,db _y) {
x = _x;y = _y;
}
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x + b.x,a.y + b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x - b.x,a.y - b.y);
}
friend Point operator * (const Point &a,const db &d) {
return Point(a.x * d,a.y * d);
}
friend Point operator / (const Point &a,const db &d) {
return Point(a.x / d,a.y / d);
}
friend db operator * (const Point &a,const Point &b) {
return a.x * b.y - a.y * b.x;
}
friend db dot(const Point &a,const Point &b) {
return a.x * b.x + a.y * b.y;
}
db norm() {
return sqrt(x * x + y * y);
}
};
struct Seg {
Point a,b;db theta;
Seg(){}
Seg(Point _a,Point _b,db _theta = 0.0) {
a = _a;b = _b;theta = _theta;
}
friend Point Cross_Point(const Seg &s,const Seg &t) {
db S1 = (s.a - t.a) * (t.b - t.a);
db S2 = (s.b - t.b) * (t.a - t.b);
return s.a + (s.b - s.a) * (S1 / (S1 + S2));
}
bool in_Seg(Point P) {
db d = (a - P) * (b - P);
if(!dcmp(d,0.0)) return false;
return dot((a - P),(b - P)) <= eps;
}
}S[105],L;
const db PI = acos(-1.0);
int N,ans[15],tot;
void Init() {
db sx,sy,tx,ty,theta,a,b;
scanf("%lf%lf%lf%lf",&sx,&sy,&tx,&ty);
L = Seg(Point(sx,sy),Point(sx + tx,sy + ty));
read(N);
for(int i = 1 ; i <= N ; ++i) {
scanf("%lf%lf%lf%lf%lf%lf",&sx,&sy,&tx,&ty,&a,&b);
theta = a / b;
S[i] = Seg(Point(sx,sy),Point(tx,ty),theta);
}
}
void Solve() {
int cnt = 10;
while(cnt--) {
int id = -1;Point t;
for(int i = 1 ; i <= N ; ++i) {
if(i == ans[tot]) continue;
Point p = Cross_Point(L,S[i]);
if(S[i].in_Seg(p) && dot(L.b - L.a,p - L.a) >= -eps) {
if(id == -1) {id = i;t = p;}
else if((p - L.a).norm() < (t - L.a).norm()) {
id = i;t = p;
}
}
}
if(id == -1) break;
ans[++tot] = id;
db d = dot(L.b - L.a,S[id].b - S[id].a);
db alpha = acos(fabs(d) / ((L.b - L.a).norm() * (S[id].b - S[id].a).norm()));
alpha = PI / 2 - alpha;
alpha = (S[id].theta + 1) * alpha;
L.b = L.a;L.a = t;
Seg ver = Seg(t,t + Point(-(S[id].b - S[id].a).y,(S[id].b - S[id].a).x));
if(dot(ver.b - ver.a,L.b - L.a) <= eps) {
ver = Seg(t,t + Point((S[id].b - S[id].a).y,-(S[id].b - S[id].a).x));
}
Point tmp = L.b - t;
if((ver.b - ver.a) * (L.b - L.a) >= -eps) alpha = -alpha;
L.b = t + Point(tmp.x * cos(alpha) - tmp.y * sin(alpha),tmp.x * sin(alpha) + tmp.y * cos(alpha));
}
if(!tot) puts("NONE");
else {
for(int i = 1 ; i <= tot ; ++i) {
out(ans[i]);space;
}
enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}