原题链接:
HDU-6164
大意:
给出一个平面镜围成的凸包,每个平面镜有一个反射衰减为
ki<0.9
若射到平面镜缝隙则能量衰减至 0,给出每个平面镜的起点和终点(逆时针顺序),和入射的向量方向。入射能量为 1.0 ,求能量衰减到 1e-4 要经过多少次碰撞。
思路:
直接硬搞,由于 ki 有范围 可以求出最多不超过100次反射一定停止。
考虑到反射和判定线段跨立,比赛的时候写成直线的一般形式,写炸了,从标称整理出一些东西。
具体实现:
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
#define MAXN 5000
#define eps 1e-9
struct point
{
double x,y;
point(double a = 0,double b = 0)
{
x = a; y = b;
}
friend point operator + (point a,point b)
{
return point(a.x+b.x,a.y+b.y);
}
friend point operator - (point a,point b)
{
return point(a.x-b.x,a.y-b.y);
}
friend double operator ^ (point a,point b)//叉积,逆时针为正
{
return a.x*b.y-a.y*b.x;
}
friend double operator * (point a,point b)
{
return a.x*b.x+a.y*b.y;
}
friend point operator * (point a,double b)
{
return point(a.x*b,a.y*b);
}
friend point operator * (double a,point b)
{
return point(a*b.x,a*b.y);
}
};
struct line//由两点确定的直线
{
point s,e;
line(point a = point(0,0),point b = point(0,0))
{
s = a; e = b;
}
};
point p[MAXN+5];
double c[MAXN+5];
int n;
point s[2];
int sgn(double x)//判断正负
{
if (x>eps) return 1;
if (x<-eps) return -1;
return 0;
}
point Get_Intersect(line a,line b)//求交点
{
double u=(a.e-a.s)^(b.s-a.s);
double v=(a.s-a.e)^(b.e-a.e);
point p;
p.x=(b.s.x*v+b.e.x*u)/(v+u);
p.y=(b.s.y*v+b.e.y*u)/(v+u);
return p;
}
int main()
{
//freopen("input.txt","r",stdin);
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&c[i]);
p[n] = p[0];
s[0] = point(0,0);
scanf("%lf%lf",&s[1].x,&s[1].y);
double now = 1.0;
int ans = 0;
bool flag = 1;
point temp;
point temp2;
line l1,l2,l3,l4;
while (now > 1e-4)
{
ans++;
for (int i=0;i<n;i++)
{
if (!sgn((p[i]-s[0])^s[1]))//光线射到缝隙
{
now = 0;
flag = 0;
break;
}
}
if (!flag) break;
for (int i=0;i<n;i++)
{
if (sgn((p[i]-s[0])^s[1]) >0 && sgn(s[1]^(p[i+1]-s[0]))>0)//由于是逆时针给方向
{
l1 = line(p[i+1],p[i]);
l2 = line(s[0],s[1]+s[0]);
temp = Get_Intersect(l1,l2);
l3 = line(temp,point(p[i+1].y-p[i].y,p[i].x-p[i+1].x)+temp);
l4 = line(s[0],point(p[i].x-p[i+1].x,p[i].y-p[i+1].y)+s[0]);
temp2 = Get_Intersect(l3,l4);
temp2 = 2*temp2-s[0];
s[0] = temp;
s[1] = temp2-s[0];
now *= c[i];
break;
}
}
}
printf("%d\n",ans);
return 0;
}