题意:两只狗,Ranga和Banga,分别在两条不同的路径上奔跑。他们每个人都花费了T秒在不同的速度下,Ranga用一个均匀速度Rm/s奔跑,Banga用一个均匀速度Sm/s奔跑。两只狗在在起点和终点的时间是相同的。让我们定义D(t)为两只狗在t时相距的距离。狗的距离定义为他们在他们的旅程的最大距离和最小距离之差。\(Dog Distance = {max(D(a)) 0 <= a <= T} - {min(D(b)) 0 <= b <= T}\)。给出两只狗的路径,你的目的是去寻找两只狗的距离。每条路径都有N个点组成。

分析:可以认为甲静止不动,乙自己沿着直线走,问题转化为求点到线段的最小距离或最大距离。这道题没有指明速度是多少,我们可以假定速度为整段路程,那么T = min(La / LenA, Lb / LenB),我们把问题拆分成简化版的问题,每次计算他俩谁先到达拐点,那么在这个时间点之间的问题就是我们刚才讨论过的"简化版"。Vector Va = (P[Sa + 1] - Pa) / La * T * LenA。先求出位移的单位向量,即\(位移向量 / 位移长度 * 时间 * 速度\),就可以得到在T时的位移向量,然后我们更新min和max,然后使用update(Pa, Pb, Pb + Vb - Va),这里假定a点静止不动,b点在动,那么Pb + Vb - Va就是b点相对于a移动的距离,然后求解a点到这条线段的距离即可。可以分为3种情况,如下
,两边是最大的距离,中间是最短距离。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;
const int N = 60;
const double eps = 1e-6;

struct Point
{
	double x, y;
	Point(double x = 0, double y = 0) : x(x), y(y) {}
};

typedef Point Vector;
Vector operator+(Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator-(Point A, Point B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator*(Vector A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator/(Vector A, double p) { return Vector(A.x / p, A.y / p); }
bool operator<(const Point& a, const Point& b)
{
	return a.x < b.x || (a.x == b.x && a.y < b.y);
}

int dcmp(double x)
{
	if (fabs(x) < eps) return 0;
	else return x < 0 ? -1 : 1;
}

bool operator==(const Point& a, const Point& b)
{
	return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }
double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }
double Length(Vector A) { return sqrt(Dot(A, A)); }

double DistanceToSegment(Point P, Point A, Point B)
{
	if (A == B) return Length(P - A);
	Vector v1 = B - A, v2 = P - A, v3 = P - B;
	if (dcmp(Dot(v1, v2)) < 0) return Length(v2);
	else if (dcmp(Dot(v1, v3)) > 0) return Length(v3);
	else return fabs(Cross(v1, v2)) / Length(v1);
}

//第一条路径的点个数,第二条路径的点个数
int A, B;
//第一条路径的点,第二条路径的点
Point P[N], Q[N];
double Min, Max;

void update(Point P, Point A, Point B)
{
	Min = min(Min, DistanceToSegment(P, A, B));
	Max = max(Max, Length(P - A));
	Max = max(Max, Length(P - B));
}

Point read_point()
{
	double x, y;
	scanf("%lf%lf", &x, &y);
	return Point(x, y);
}

int main()
{	
	int t;
	scanf("%d", &t);

	int c = 0;
	while (t--)
	{
		//第一条路径的点个数,第二条路径的点个数
		scanf("%d%d", &A, &B);
		for (int i = 0; i < A; ++i) P[i] = read_point();
		for (int i = 0; i < B; ++i) Q[i] = read_point();

		double LenA = 0, LenB = 0;
		for (int i = 0; i < A - 1; ++i) LenA += Length(P[i + 1] - P[i]);
		for (int i = 0; i < B - 1; ++i) LenB += Length(Q[i + 1] - Q[i]);

		//拐点编号
		int Sa = 0, Sb = 0;
		//现处于的点
		Point Pa = P[0], Pb = Q[0];
		Min = 1e9, Max = -1e9;

		while (Sa < A - 1 && Sb < B - 1)
		{
			double La = Length(P[Sa + 1] - Pa);
			double Lb = Length(Q[Sb + 1] - Pb);
			//到达拐点的最短时间
			double T = min(La / LenA, Lb / LenB);
			//位移向量
			Vector Va = (P[Sa + 1] - Pa) / La * T * LenA;
			Vector Vb = (Q[Sb + 1] - Pb) / Lb * T * LenB;
			update(Pa, Pb, Pb + Vb - Va);
			Pa = Pa + Va;
			Pb = Pb + Vb;
			if (Pa == P[Sa + 1]) ++Sa;
			if (Pb == Q[Sb + 1]) ++Sb;
		}
		printf("Case %d: %.0lf\n", ++c, Max - Min);
	}

	return 0;
}