upc3020: Keeping the Dogs Apart

Despite the unfortunate incident last summer,which resulted in ten little puppies, you have been tasked with taking care of your neighbors’ dogs again. Shadow and Lydia may be very  cute mutts, but this year you have strict instructions to walk them one by one. However, you have other things to do during the summer than walking dogs! Like playing fetch and solving programming problems! It seems terribly inefficient to walk the dogs one at a time.
Shadow and Lydia have a particular walk they each prefer and know by heart. If you just let them out, they will follow their favorite walk, eventually ending up in their respective doghouses. Problem solved!
Sadly, you realize that if you just let both dogs out at the same time and let them do their walks on their own, they might get too close to each other. If they get too close, they will leave their favorite walk to “have some fun” and you are not sure you can find good homes for any more puppies. To ensure this does not happen, you need to calculate the minimum distance between the dogs when they are out walking on their own.
Both dogs start at the same time and keep exactly the same pace. Immediately after a dog arrives at its doghouse it stays inside and goes to sleep, so we no longer need to worry about the distance to the other dog, even though the other dog may still walk for a while longer. Note that a dog is still awake at the exact moment of entering its house and falls asleep immediately after entering.

输入

The first line of input consists of an integer n (2 ≤ n ≤ 100 000), the number of points describing the walk of Shadow. The next n lines contain 2 integers each, giving the x and y coordinates of Shadow’s walk. Two consecutive points in the walk always differ in at least one coordinate.
All coordinates are non-negative and at most 10 000. Similarly, the next line contains an integer m (2 ≤ m ≤ 100 000), the number of points describing the walk of Lydia. The next m lines describe its walk in the same format as for Shadow.

输出

Output the minimum distance between the two dogs during their walks. The numbers should be accurate to an absolute or relative error of at most 10-4 .

样例输入

2
0 0
10 0
2
30 0
15 0

样例输出

10

详细做法看这个:https://blog.csdn.net/xbb224007/article/details/79846472

模拟,但是这题可能会在精度上出错,所以用的long double。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 100005;

struct point {
	double x, y;
	point(double x = 0.0, double y = 0.0):x(x),y(y) {};
};

long double dis(point p1, point p2) {
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}

long double slove(point n1, point n2, point n3, point n4) {
	long double len = dis(n1, n2);
	point e1((n2.x - n1.x) / len, (n2.y - n1.y) / len);
	point e2((n4.x - n3.x) / len, (n4.y - n3.y) / len);

	long double a = (e1.x - e2.x) * (e1.x - e2.x) + (e1.y - e2.y) * (e1.y - e2.y);
	long double b = 2.0 * ((n1.x - n3.x) * (e1.x - e2.x) + (n1.y - n3.y) * (e1.y - e2.y));
	long double c = (n1.x - n3.x) * (n1.x - n3.x) + (n1.y - n3.y) * (n1.y - n3.y);
	long double t = -1.0;

	if(a > 0)
		t = -b / 2.0 / a;
	if(t >= 0 && t <= len)
		return sqrt(a * t * t + b * t + c);
	return min(dis(n1, n3), dis(n2, n4));
}

point a[maxn], b[maxn];
int main() {
	int n, m;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%lf%lf", &a[i].x, &a[i].y);
	scanf("%d", &m);
	for (int i = 1; i <= m; i++)
		scanf("%lf%lf", &b[i].x, &b[i].y);
	int i = 1, j = 1;
	long double minn = 1.0 * INF;
	while (i < n && j < m) {
		long double l1 = dis(a[i], a[i + 1]);
		long double l2 = dis(b[j], b[j + 1]);
		long double ans;
		if (l1 == l2) {
			ans = slove(a[i], a[i + 1], b[j], b[j + 1]);
			i++;
			j++;
		} else if(l1 > l2) {
			point t = a[i];
			a[i].x += l2 * (a[i + 1].x - a[i].x) / l1;
			a[i].y += l2 * (a[i + 1].y - a[i].y) / l1;
			ans = slove(t, a[i], b[j], b[j + 1]);
			j++;
		} else {
			point t = b[j];
			b[j].x += l1 * (b[j + 1].x - b[j].x) / l2;
			b[j].y += l1 * (b[j + 1].y - b[j].y) / l2;
			ans = slove(a[i], a[i + 1], t, b[j]);
			i++;
		}
		minn = min(minn, ans);
	}
	printf("%.10lf\n", (double)minn);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值