Description
给定一个x*y的矩形,矩形里有两个小球,它们初始的速度都是(1, 1),即向右上方。碰壁后会反弹(墙壁为x=0,x=n,y=0,y=m这4条直线),问这两个小球能否相遇,输出相遇的坐标或"Collision will not happen."
Input
第一行一个整数T,表示数据的组数。
每组数据第一行两个整数x,y,表示矩形的长和宽。
第二行4个整数x1, y1, x2, y2,表示这两个小球的初始坐标。
Output
对于每一组数据,第一行输出“Case #x:”,x是数据的编号(从1开始)。
第二行输出两个1位小数,表示两小球相遇的坐标,或者输出“Collision will not happen.”,如果两小球永远不能相遇的话。
Sample Input
3
10 10
1 1 9 9
10 10
0 5 5 10
10 10
1 0 1 10
Sample Output
Case #1:
6.0 6.0
Case #2:
Collision will not happen.
Case #3:
6.0 5.0
Solution
模拟两个小球的运动,当然不能一步一步走,必定会T,只能一段一段地模拟,即:
- 分别求出两小球到达墙壁的距离,设分别为
dist1,dist2
,
接下来两小球要走的距离是 min(dist1,dist2) 。 - 判断在这段路程中两小球是否相遇,如果是则输出并返回。
- 使小球移动,并重复此过程。如果重复了很多次还不能相遇则return false。
说起来简单其实很恶心,我会说我调了一个晚上吗?
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <utility>
#define pii pair<int, int>
#define mp(a, b) make_pair(a, b)
#define getb(x, y, k) (y - (k * x))
#define getx(k1, b1, k2, b2) ((b1 - b2) / (k2 - k1))
#define gety(k, x, b) (k * x + b)
#define getk(p) (p & 1) ? 1 : -1
#define move(nax, nay, nbx, nby) ax = nax, ay = nay, bx = nbx, by = nby;
#define eps 1e-8
using namespace std;
int T, n, m;
int ax, ay, bx, by;
int pa, pb; // a和b的方向。1:右上,2:右下,3:左下,4:左上
bool check(int da, int db, int px, int py) {
if (fabs(da - db) > eps) return false;
if (px < -eps || py < -eps || px > n + eps || py > m + eps) return false;
if (fabs(ax - bx) < eps && pa + pb != 5) return false;
if (fabs(ay - by) < eps && pa + pb == 5) return false;
return true;
}
void change(int x, int y, int &p) {
if (x == n) p = (p == 1) ? 2 : ((p == 4) ? 3 : p);
if (y == m) p = (p == 1) ? 4 : ((p == 2) ? 3 : p);
if (!x) p = (p == 2) ? 1 : ((p == 3) ? 4 : p);
if (!y) p = (p == 3) ? 2 : ((p == 4) ? 1 : p);
}
int getdist(int x, int y, int pos) {
switch(pos) {
case 1 : return min(n - x, m - y);
case 2 : return min(x, m - y);
case 3 : return min(x, y);
case 4 : return min(n - x, y);
}
}
pii next_pos(int x, int y, int pos, int dist) {
int dx, dy;
if (pos == 1) dx = dy = 1;
else if (pos == 2) dx = -1, dy = 1;
else if (pos == 3) dx = dy = -1;
else dx = 1, dy = -1;
return mp(x + dx * dist, y + dy * dist);
}
bool solve() {
int cnt = 0;
while (cnt++ <= 1000000) {
change(ax, ay, pa), change(bx, by, pb);
int dist1 = getdist(ax, ay, pa);
int dist2 = getdist(bx, by, pb);
int dist = min(dist1, dist2);
// na,nb是移动后两小球的坐标
pii na = next_pos(ax, ay, pa, dist);
pii nb = next_pos(bx, by, pb, dist);
// k,b是直线方程
int ka = getk(pa);
int kb = getk(pb);
int ba = getb(ax, ay, ka);
int bb = getb(bx, by, kb);
if (ka == kb && ba == bb && pa != pb || (ax == bx && ay == by)) {
double px = (double(ax) + double(bx)) / 2.0;
double py = (double(ay) + double(by)) / 2.0;
printf("%.1lf %.1lf\n", px, py);
return true;
} else if (ka != kb) {
double px = getx(double(ka), double(ba), double(kb), double(bb));
double py = gety(ka, px, ba);
double da = abs(px - ax);
double db = abs(px - bx);
if (check(da, db, px, py)) {
printf("%.1lf %.1lf\n", px, py);
return true;
}
}
move(na.first, na.second, nb.first, nb.second);
}
return false;
}
int main() {
// freopen("c.in", "r", stdin);
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++) {
printf("Case #%d:\n", cas);
scanf("%d %d", &n, &m);
scanf("%d %d %d %d", &ax, &ay, &bx, &by);
pa = pb = 1;
if (!solve()) printf("Collision will not happen.\n");
}
return 0;
}