hdu 5114 Collision (扩展欧几里得)
来源:互联网 发布:围棋文化内涵 知乎 编辑:程序博客网 时间:2024/06/03 19:04
Collision
Problem Description
Matt is playing a naive computer game with his deeply loved pure girl.
The playground is a rectangle with walls around. Two balls are put in different positions inside the rectangle. The balls are so tiny that their volume can be ignored. Initially, two balls will move with velocity (1, 1). When a ball collides with any side of the rectangle, it will rebound without loss of energy. The rebound follows the law of refiection (i.e. the angle at which the ball is incident on the wall equals the angle at which it is reflected).
After they choose the initial position, Matt wants you to tell him where will the two balls collide for the first time.
The playground is a rectangle with walls around. Two balls are put in different positions inside the rectangle. The balls are so tiny that their volume can be ignored. Initially, two balls will move with velocity (1, 1). When a ball collides with any side of the rectangle, it will rebound without loss of energy. The rebound follows the law of refiection (i.e. the angle at which the ball is incident on the wall equals the angle at which it is reflected).
After they choose the initial position, Matt wants you to tell him where will the two balls collide for the first time.
Input
The first line contains only one integer T which indicates the number of test cases.
For each test case, the first line contains two integers x and y. The four vertices of the rectangle are (0, 0), (x, 0), (0, y) and (x, y). (1 ≤ x, y ≤ 105)
The next line contains four integers x1, y1, x2, y2. The initial position of the two balls is (x1, y1) and (x2, y2). (0 ≤ x1, x2 ≤ x; 0 ≤ y1, y2 ≤ y)
For each test case, the first line contains two integers x and y. The four vertices of the rectangle are (0, 0), (x, 0), (0, y) and (x, y). (1 ≤ x, y ≤ 105)
The next line contains four integers x1, y1, x2, y2. The initial position of the two balls is (x1, y1) and (x2, y2). (0 ≤ x1, x2 ≤ x; 0 ≤ y1, y2 ≤ y)
Output
For each test case, output “Case #x:” in the first line, where x is the case number (starting from 1).
In the second line, output “Collision will not happen.” (without quotes) if the collision will never happen. Otherwise, output two real numbers xc and yc, rounded to one decimal place, which indicate the position where the two balls will first collide.
In the second line, output “Collision will not happen.” (without quotes) if the collision will never happen. Otherwise, output two real numbers xc and yc, rounded to one decimal place, which indicate the position where the two balls will first collide.
题目大意:有一个长宽分别为 x+1 y+1的矩形,左下角坐标为 0,0。现在有两个起点 坐标(x1,y1)(x2,y2) 他们移动速度都是(1,1),每秒横坐标向前一个单位,纵坐标向上一个单位,碰到边界会反弹。 问两个球会不会碰撞,如果能碰撞输出第一次碰撞的位置。
解题思路:
解决这类碰撞问题的常见套路都是将速度正交分解,分别考虑横坐标和纵坐标。
首先我们注意到一个问题是碰撞的点有可能在格中间,所以我们将题目中所有的数据都翻倍,也就是奇数节点代表的是以前的格中点。最后输出答案的时候记得÷2就可以了。
然后我们分析横坐标碰撞的情况,画图分析容易得到 (x1 + x2 +2t ) = 0 (mod 2x)
同理有 (y1 + y2 + 2t) = 0 ( mod 2y)
易得 t = k1 * x - (x1 + x2)/2
t = k2 * y - (y1 + y2)/2
联立两个等式,我们可以发现可以应用扩展欧几里得求解。最后要保证时间 t 一定是正数即可。
注意 t 可以选择的周期是 lcm(x,y)
AC代码:
#include <bits/stdc++.h>using namespace std;#define LL long long#define ll long longll exgcd(ll a, ll b, ll &x, ll &y) // a*x + b*y = gcd(a,b){ if(b==0) { x = 1; y = 0; return a; } ll d = exgcd(b,a%b,x,y); ll temp = x; x = y; y = temp - a/b*y; return d;}int main(){ int t; scanf("%d", &t); for(int cas = 1 ; cas <= t ; cas++){ LL x, y; scanf("%I64d%I64d", &x, &y); LL x1, y1, x2, y2; scanf("%I64d%I64d%I64d%I64d", &x1, &y1, &x2, &y2); LL k1, k2; x1 *= 2, x2 *= 2, y1 *= 2, y2 *= 2, x *= 2, y *= 2; LL d = exgcd(x, y, k1, k2); printf("Case #%d:\n", cas); double ansx, ansy; ll t; if(x1 == x2 && y1 == y2) t = 0; else if(x1 == x2) t = (2 * y - y1 - y2) / 2; else if(y1 == y2) t = (2 * x - x1 - x2) / 2; else if(((x1 + x2 - y1 - y2) / 2) % d != 0){ printf("Collision will not happen.\n"); continue; } else{ LL k = ((x1 + x2 - y1 - y2) / 2 / d); t = k1 * x * k - (x1 + x2) / 2; k = (x * y) / d; //可选时间的周期 t = (t % k + k) % k;//需要把时间处理为非负数 } ansx = (x1 + t) % (2 * x); if(ansx >= x) ansx = 2 * x - ansx; ansy = (y1 + t) % (2 * y); if(ansy >= y) ansy = 2 * y - ansy; printf("%.1f %.1f\n", ansx / 2.0, ansy / 2.0); } return 0;}
阅读全文
0 0
- hdu 5114 Collision (扩展欧几里得)
- HDU 5514 Collision(扩展欧几里得+解方程)——2014ACM/ICPC亚洲区北京站
- hdu 5114 Collision
- Collision (hdu-5114)
- hdu 2669 扩展欧几里得
- hdu 1576 扩展欧几里得
- HDU 1576 扩展欧几里得
- HDU 2669 扩展欧几里得
- hdu 1576 扩展欧几里得
- HDU 4180 扩展欧几里得
- hdu-2669 扩展欧几里得
- HDU 2669 扩展欧几里得
- HDU 1576 扩展欧几里得
- hdu 1576 扩展欧几里得
- 扩展欧几里得 Romantic (HDU
- hdu-3270(扩展欧几里得)
- hdu 1576扩展欧几里得算法
- HDU 2669 Romantic 扩展欧几里得
- 点到点法式平面投影点的计算
- Closure谷歌js,YUI Compressor雅虎…
- MySQL中TIMESTAMPDIFF和TIMESTAMPADD函数的用法
- linux 下查看端口号命令
- nice设置进程优先级
- hdu 5114 Collision (扩展欧几里得)
- cheat engine 教程
- c++ static
- linux下iptables配置详解
- nginx 优化系列之worker_con…
- python将秒数转化为时间格式
- apache 403 forbidden 错误解决方…
- 推理题-谁是小偷?
- beforeunload事件