UVA 11796 - Dog Distance 向量的应用

58 篇文章 0 订阅
7 篇文章 0 订阅

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2896

题目大意:

甲和乙两条狗分别沿着一条折线跑,它们速度未知,但同时出发并且同时到达终点,并且都是匀速奔跑。求奔跑过程中两只狗的最大距离与最小距离之差。

思路:

因为运动是相对的,我们可以认为甲静止不动,乙沿着直线走。则问题就转化为点到线段的最小距离。

那么,我们对于每段分析,看谁先到达该线段的终点,则该段可以用上面的方法求。

把a看成不动的,则有b运动到了cb+vb-va(其中va,vb分别为a和b的位移向量,ca,cb分别为a和b初始位置)

那么就转换为sa到线段cb+vb-va的距离。(最小距离为点到直线,而最大距离一定在线段两边)

至于速度的表示,设1S到达终点,那么速度就是总长。

PS:直接用模版就是爽。哈哈

#include<cstdio>  
#include<cmath>  
#include<algorithm>  
using namespace std;  
const int MAXN=50+10;
const int INF=99999999;
double ans_max,ans_min;
struct Point 
{
	double x,y;
	Point(double x=0,double y=0):x(x),y(y){ }
};
typedef Point Vector;  
const double eps = 1e-8;
int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; }
Vector operator + (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); }  
Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }  
Vector operator * (const Vector& A, double p) { return Vector(A.x*p, A.y*p); }  
Vector operator / (const Vector& A, double p) { return Vector(A.x/p, A.y/p); } 
bool operator == (const Point& a, const Point &b) {
	return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}

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

double DistanceToSegment(const Point& P, const Point& A, const 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);
}

void update(Point P,Point A,Point B)
{
	ans_max=max(ans_max,Length(P-A));//最大的一定在端点
	ans_max=max(ans_max,Length(P-B));
	ans_min=min(ans_min,DistanceToSegment(P,A,B));//最小的为点到直线的距离
}

Point a[MAXN],b[MAXN];

int main()
{
	int T,kase=1;
	scanf("%d",&T);
	while(T--)
	{
		int A,B;
		scanf("%d%d",&A,&B);
		for(int i=0;i<A;i++)
			scanf("%lf%lf",&a[i].x,&a[i].y);

		for(int i=0;i<B;i++)
			scanf("%lf%lf",&b[i].x,&b[i].y);
		
		double lena=0,lenb=0;   //总长度
		for(int i=0;i<A-1;i++)
			lena+=Length(a[i+1]-a[i]);
		for(int i=0;i<B-1;i++)
			lenb+=Length(b[i+1]-b[i]);

		int ia=0,ib=0;  //index 
		Point ca=a[0],cb=b[0]; //current point
		ans_max=-INF,ans_min=INF;
		while(ia<A-1 && ib<B-1)
		{
			double sa=Length(a[ia+1]-ca);   //到下一个拐点的距离
			double sb=Length(b[ib+1]-cb);
			double ta=sa/lena;     //设到终点都为1S,那么每一段时间就是除以总长。
			double tb=sb/lenb;
			double t=min(ta,tb);   
			Vector va=(a[ia+1]-ca)/sa*t*lena;
			Vector vb=(b[ib+1]-cb)/sb*t*lenb;
			update(ca,cb,cb+vb-va);//把a看成静止的,则b相对从cb运动到了vb-va处。
			ca=ca+va;
			cb=cb+vb;
			if(ca==a[ia+1]) ia++;
			if(cb==b[ib+1]) ib++;
		}
		printf("Case %d: %.0lf\n",kase++,ans_max-ans_min);
	}

	return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值