hdu5114 Collision [模拟]

来源:互联网 发布:知乎 股市入门书籍 编辑:程序博客网 时间:2024/06/18 08:48

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

310 101 1 9 910 100 5 5 1010 101 0 1 10

Sample Output

Case #1:6.0 6.0Case #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-8using 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;}
0 0