题意:给N (2≤N≤11) 个圆,半径都为r,圆心位置不同,都在一个矩形内。矩形左下角是(0,0),右上角是(W,H)。保证初始每个圆都不相交或相切。要求打第一个圆,初始方向是(Vx, Vy),这个圆会不断地与矩形边界发生无能量损失碰撞,镜面反射。小圆只能运动10000单位长度,问小圆碰撞到的第一个圆是哪个,或者不会发生碰撞就停下了。
链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2537
解法:就模拟,但是不同的优化会使得代码量级别不同。做一个优化,将第一个圆看成一个点,就是它的圆心,其他圆半径扩大一倍,将矩形缩小,上左下右边界分别向下、向右、向上、向左移动 r。然后就变成一条射线发生镜面反射,问第一个碰到的圆是哪一个即可。。直接模拟。
//Hello. I'm Peter.
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
using namespace std;
#define peter cout<<"i am peter"<<endl
typedef long long ll;
const double eps = 1e-9, pi = acos(-1.0);
inline int sgn(double x){
if(fabs(x) < eps) return 0;
else return x > 0 ? 1 : -1;
}
struct Point{
double x, y;
Point(){};
Point(double x1, double y1){
x = x1, y = y1;
}
};
typedef Point Vector;
Vector operator - (Vector a, Vector b){
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator + (Vector a, Vector b){
return Vector(a.x + b.x, a.y + b.y);
}
double operator % (Vector a, Vector b){
return a.x * b.y - a.y * b.x;
}
double operator * (Vector a, Vector b){
return a.x * b.x + a.y * b.y;
}
Vector operator * (Vector a, double b){
return Vector(a.x * b, a.y * b);
}
Point getp(Point p1, Vector v1, Point p2, Vector v2, double &t){
t = ((p2 - p1) % v2) / (v1 % v2);
return p1 + v1 * t;
}
double Length(Vector v){
return sqrt(v.x * v.x + v.y * v.y);
}
double angle(Vector v){
return atan2(v.y, v.x);
}
double angle(Vector v1, Vector v2){
double a = angle(v1) - angle(v2);
while(sgn(a) < 0) a += 2 * pi;
while(sgn(a - 2*pi) >= 0) a -= 2 * pi;
a = fmin(a, 2 * pi - a);
return a;
}
Vector Rotate(Vector v, double rad){
return Vector(v.x * cos(rad) - v.y * sin(rad), v.x * sin(rad) + v.y * cos(rad));
}
Vector reflect(Vector v, Vector minor){
if(sgn(v * minor) < 0) minor = minor * (-1);
double a = angle(v, minor);
if(sgn(v % minor) > 0) v = Rotate(v, 2 * a);
else v = Rotate(v, - 2 * a);
return v;
}
double dis(Point p, Point p1, Vector v1){
return fabs((p - p1) % v1) / Length(v1);
}
int n;
struct Wall{
Point p[2];
Vector v;
}wall[10];
struct Circle{
Point p;
double r;
}cir[30];
double get(Point p, Vector v, Circle cir){
double a = v.x, b = p.x - cir.p.x, c = v.y, d = p.y - cir.p.y;
double e = a * a + c * c, f = 2 * (a * b + c * d), g = b * b + d * d - cir.r * cir.r;
double delta = f * f - 4 * e * g;
double t1, t2;
t1 = (-f - sqrt(delta)) / (2 * e);
t2 = (-f + sqrt(delta)) / (2 * e);
Point p1, p2;
p1 = p + v * t1, p2 = p + v * t2;
return fmin(Length(p1 - p), Length(p2 - p));
}
const double maxid = 10000;
int solve(Point nowp, Vector nowv, double nowdis){
double mini = 1e9;
int w = 0;
for(int i = 2; i <= n; i++){
double d = dis(cir[i].p, nowp, nowv);
if(sgn(d - cir[i].r) <= 0){
if(sgn((cir[i].p - nowp) * nowv) > 0){
double dis = get(nowp, nowv, cir[i]);
if(sgn(dis - mini) < 0){
mini = dis;
w = i;
}
}
}
}
if(w != 0){
double dis = get(nowp, nowv, cir[w]);
if(sgn(nowdis + dis - maxid) > 0) return -1;
else return w;
}
int nmaxi = 0;
w = 0;
double maxdis = -1;
Point px = Point(0, 0);
for(int i = 1; i <= 4; i++){
if(sgn(wall[i].v % nowv) == 0) continue;
double t;
Point x = getp(wall[i].p[0], wall[i].v, nowp, nowv, t);
if(sgn(t) >= 0 && sgn(t - 1) <= 0 && sgn((x - nowp) * nowv) > 0){
double dis = Length(x - nowp);
if(sgn(dis - maxdis) > 0){
maxdis = dis;
nmaxi = 1;
px = x;
w = i;
}
else if(sgn(dis - maxdis) == 0){
nmaxi++;
}
}
}
double dis = Length(px - nowp);
if(sgn(nowdis + dis - maxid) >= 0) return -1;
nowdis += dis;
nowp = px;
if(nmaxi == 2) nowv = nowv * (-1);
else nowv = reflect(nowv, wall[w].v);
return solve(nowp, nowv, nowdis);
}
int main(){
int w, h, r, x, y;
while(scanf("%d",&n) == 1 && n != 0){
scanf("%d%d%d%d%d",&w,&h,&r,&x,&y);
Point p[10];
p[0] = Point(0, 0) + Vector(r, r);
p[1] = Point(w, 0) + Vector(-r, r);
p[2] = Point(w, h) + Vector(-r, -r);
p[3] = Point(0, h) + Vector(r, -r);
int t = 0;
for(int i = 1; i <= 4; i++){
wall[i].p[0] = p[t];
wall[i].p[1] = p[(t + 1) % 4];
wall[i].v = wall[i].p[1] - wall[i].p[0];
t++;
}
for(int i = 1; i <= n; i++){
int x, y;
scanf("%d%d",&x,&y);
cir[i].p.x = x, cir[i].p.y = y;
cir[i].r = 2 * r;
}
printf("%d\n",solve(cir[1].p, Vector(x, y), 0));
}
return 0;
}