2020“图灵杯”趣味网络邀请赛 A. 相遇(分类讨论+数学计算)

2020“图灵杯”趣味网络邀请赛 A. 相遇

题解

  • 路径总长 100 100 100,速度也小于等于 10 10 10,而 k k k却特别大,想到可以依次找出所有相遇位置,当出现循环则退出,可以证明这样复杂度是可以过的。
  • 如何快速的找到每次相遇的位置呢?
  • 直接分类讨论,相向时可以计算相遇,追及且能追上时可以计算相遇,其余情况则让两个人往他们当前方向的端点跑,设两人到端点时间分别为 t x , t y tx,ty tx,ty,则计算时间 m i n ( t x , t y ) min(tx,ty) min(tx,ty)后的位置(因为这样做计算简便)。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
#define ld long double
#define N 100010
ld a[N];
ll read() {
	ll s = 0;
	char x = getchar();
	while(x < '0' || x > '9') x = getchar();
	while(x >= '0' && x <= '9') s = s * 10 + x - 48, x = getchar();
	return s;
}
int main() {
	int tn = read();
	while(tn--) {
		ll k = read();
		ld v1 = read(), v2 = read(), X = read();
		ld x = 0, ox = 1, y = X, oy = -1;
		int s = 0, t = 0, i;
		while(s == 0 || x != 0 || y != X || oy != -1) {
			if(ox == 1 && oy == -1 && x < y) {
				x = y = x + (y - x) / (v1 + v2) * v1;
				ox = -1, oy = 1;
				a[++s] = x;
				for(i = 1; i < s; i++) if(a[i] == x) {
					t = i;
					break;
				}
				if(t) break;
			}
			else if(ox == -1 && oy == 1 && y < x) {
				x = y = y + (x - y) / (v1 + v2) * v2;
				ox = 1, oy = -1;
				a[++s] = x;
				for(i = 1; i < s; i++) if(a[i] == x) {
					t = i;
					break;
				}
				if(t) break;
			}
			else if(v1 >= v2 && ox == oy && ox == 1 && x < y && x + (y - x) / (v1 - v2) * v1 <= 100) {
				x = y = x + (y - x) / (v1 - v2) * v1, ox = -1;
				a[++s] = x;
				for(i = 1; i < s; i++) if(a[i] == x) {
					t = i;
					break;
				}
				if(t) break;
			}
			else if(v1 >= v2 && ox == oy && ox == -1 && x > y && x - (x - y) / (v1 - v2) - v1 >= 0) {
				x = y = x - (x - y) / (v1 - v2) * v1, ox = 1;
				a[++s] = x;
				for(i = 1; i < s; i++) if(a[i] == x) {
					t = i;
					break;
				}
				if(t) break;
			}
			else if(v1 <= v2 && ox == oy && oy == 1 && y < x && y + (x - y) / (v2 - v1) * v2 <= 100) {
				x = y = y + (x - y) / (v2 - v1) * v2, oy = -1;
				a[++s] = x;
				for(i = 1; i < s; i++) if(a[i] == x) {
					t = i;
					break;
				}
				if(t) break;
			}
			else if(v1 <= v2 && ox == oy && oy == -1 && y > x && y - (y - x) / (v2 - v1) * v2 >= 0) {
				x = y = y - (y - x) / (v2 - v1) * v2, oy = 1;
				a[++s] = x;
				for(i = 1; i < s; i++) if(a[i] == x) {
					t = i;
					break;
				}
				if(t) break;
			}
			else if(ox == -1) {
				ld tx = x / v1;
				if(oy == -1) {
					ld ty = y / v2;
					if(tx <= ty) {
						x = 0, y -= v2 * tx, ox = 1;
						if(y == 0) oy = 1;
					}
					else {
						y = 0, x -= v1 * ty, oy = 1;
						if(x == 0) ox = 1;
					}
				}
				else  {
					ld ty = (100.0 - y) / v2;
					if(tx <= ty) {
						x = 0, y += v2 * tx, ox = 1;
						if(y == 100) oy = -1;
					}
					else {
						y = 100, x -= v1 * ty, oy = -1;
						if(x == 0) ox = 1;
					}
				}
			}
			else {
				ld tx = (100.0 - x) / v1;
				if(oy == -1) {
					ld ty = y / v2;
					if(tx <= ty) {
						x = 100, y -= v2 * tx, ox = -1;
						if(y == 0) oy = 1;
					}
					else {
						y = 0, x += v1 * ty, oy = 1;
						if(x == 100) ox = -1;
					}
				}
				else {
					ld ty = (100.0 - y) / v2;
					if(tx <= ty) {
						x = 100, y += tx * v2, ox = -1;
						if(y == 100) oy = -1;
					}
					else {
						y = 100, x += ty * v1, oy = -1;
						if(x == 100) ox = -1;
					}
				}
			}
		}
		if(!t) printf("%.8Lf
", a[(k - 1) % s + 1]);
		else if(k <= t) printf("%.8Lf
", a[k]);
		else {
			k -= t, s -= t;
			printf("%.8Lf
", a[(k - 1) % s + 1 + t]);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/LZA119/p/14279503.html