HDU 4793 Collision (计算几何)
There's a round medal fixed on an ideal smooth table, Fancy is trying to throw some coins and make them slip towards the medal to collide. There's also a round range which shares exact the same center as the round medal, and radius of the medal is strictly less than radius of the round range. Since that the round medal is fixed and the coin is a piece of solid metal, we can assume that energy of the coin will not lose, the coin will collide and then moving as reflect.
Now assume that the center of the round medal and the round range is origin ( Namely (0, 0) ) and the coin's initial position is strictly outside the round range.
Given radius of the medal R m, radius of coin r, radius of the round range R, initial position (x, y) and initial speed vector (vx, vy) of the coin, please calculate the total time that any part of the coin is inside the round range. Please note that the coin might not even touch the medal or slip through the round range.
Input
There will be several test cases. Each test case contains 7 integers R m, R, r, x, y, vx and vy in one line. Here 1 ≤ R m < R ≤ 2000, 1 ≤ r ≤ 1000, R + r < |(x, y)| ≤ 20000, 1 ≤ |(vx, vy)| ≤ 100.
Output
For each test case, please calculate the total time that any part of the coin is inside the round range. Please output the time in one line, an absolute error not more than 1e -3 is acceptable.
Sample Input
5 20 1 0 100 0 -1
5 20 1 30 15 -1 0
Sample Output
30.000
29.394
题意:
光滑的桌面上有一个大圆(半径为R)和一个小圆盘(半径为Rm),它们圆心同为(0,0),现有一枚严格在大圆以外的硬币(半径为r)平放在桌面上,坐标(x,y),以速度(vx,vy)运动,若硬币撞到圆盘上会被反弹,碰撞期间动量守恒(速度大小不变),求该硬币所有部位在大圆内运动的总时间,硬币有可能未进入大圆区域或未碰撞。
三种情况:(首先求出硬币运动轨迹和(0,0)的距离d)
1.硬币没进入大圆区域(d>=R+r)
答案肯定是0啦
2.硬币进入了大圆区域没有碰到圆盘(Rm+r<=d<R+r)
由图勾股定理求?的地方即答案(手糊小破图多多包涵hhhh)
3.硬币进入了大圆区域并且碰到了圆盘被反弹了(d<Rm+r)
再来看一下下面这个小破图:
很显然我们要求的是AB+BC,怎么办呢,我首先想到的是求角度,但是琢磨了一会怎么着也不好求,求角的伙伴们放弃吧还是。那现在我们假设这个硬币撞到了圆盘,但是没反弹,最后按着它的原始路线飞出了大圆区域,由反弹我们可以知道AB==BC,而AB==DE,那么问题转化为了求AB+DE。AB+DE=AE-BD 从而转化到了第二种情况求AE和BD(鼓掌鼓掌!!!)
WA了两发,第一发没有注意到离大圆越来越远的情况,第二发没除以速度qwq
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int Rm,R,r,vx,vy,x,y;
while(scanf("%d%d%d%d%d%d%d",&Rm,&R,&r,&x,&y,&vx,&vy)!=EOF)
{
double t,d,v;
d=1.0*abs(vx*y-vy*x)/sqrt(vy*vy+vx*vx);///硬币轨迹与(0,0)的距离
v=1.0*sqrt(vx*vx+vy*vy);///初速度
if(d>=R+r)///第一种情况 根本交不到
t=0;
else if(Rm+r<=d&&d<R+r)///进入大圆未碰撞
{
if(x*vx+y*vy>=0)///第一次WA漏掉的地方,求向量(x,y)和(vx,vy)的数量积,为正说明夹角小于90度,硬币向远离大圆的区域运动,画个图就知道了
t=0;
else
t=2.0*sqrt((R+r)*(R+r)-d*d)/v;///求的是时间,要除以速度
}
else
{
if(x*vx+y*vy>=0)
t=0;
else
t=(2.0*sqrt((R+r)*(R+r)-d*d)-2.0*sqrt((Rm+r)*(Rm+r)-d*d))/v;
}
printf("%.3f\n",t);
}
return 0;
}