狗A,狗B,分别沿着两条折线奔跑,两只狗的速度未知。
已知:
两只狗同时出发,同时到达,并且都是匀速奔跑。
可以假设奔跑的总时长为 1s,这样两只狗的速度就等于折线的长度。速度就变成已知啦。
求:狗A , 狗B,在奔跑过程中最近距离,和最远距离的差。
这题感觉用到了DP的思想。
把这线段以拐点为划分,酱紫就得到了一条一条的线段。那么可以看做:
在某一时间内,两条狗都在线段上奔跑。
划分为子问题,就是每次解出这些线段。
由物理的相对运动知道。
假设狗A的速度为av,狗B的速度为bv,那么可以看做,狗A静止不动,狗B以(bv-av)的速度奔跑。
由此可以化简为点到直线的距离。
画图推一下就知道了,最大距离是一定在端点上的。
设立两个变量pa,pb,表示狗A,狗B当前出发的点。
sa+1,sb+1,就是目前这一线段的终点,看做子问题就是狗要跑到这里就好了。
算出先到达拐点的狗花费的时间。
再算出两只狗的位移。到达拐点的狗就更新当前点,以此 sx+1 拐点为下一次奔跑的起点。
另外一只狗以 sx+1 为终点,上一次花费 t 时间跑到的地方为起点。
如此循环更新 :)
具体--》
两条狗以 A,B 起点,狗A先到达拐点C,狗B此时到达D点。
那么更新最大值最小值。更新当前点。
狗A,下一次的起点为 C 点,终点 E。
狗B,下一次的起点为 D 点,终点..哦 我忘记画出来了!!自己懂!!
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct point
{
double x,y,d;
point(double a,double b):x(a),y(b){}
point(){}
void read() { scanf("%lf%lf",&x,&y);}
};
typedef point vec;
vec operator + ( vec a, vec b) { return vec(a.x+b.x,a.y+b.y);}
vec operator - ( point a, point b) { return vec(a.x-b.x,a.y-b.y);}
vec operator * ( vec a, double p) { return vec(a.x*p,a.y*p);}
vec operator / ( vec a, double p) { return vec(a.x/p,a.y/p);}
double dot( vec a,vec b) { return a.x*b.x + a.y*b.y;}
double length( vec a) { return sqrt( dot(a,a));}
const int maxn = 50+5;
int t,anum,bnum;
point ap[maxn],bp[maxn];
double mx,mi;
double cross( vec a,vec b ){ return a.x*b.y - a.y*b.x;}
const double eps =1e-6;
int dcmp( double x)
{
if( fabs(x)<eps )return 0;
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 distosegment( point p,point a,point b)
{
if( a==b )
return length(p-a);
vec v1 = b-a;
vec v2 = p-a;
vec 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)
{
mi = min(mi,distosegment(p,a,b));
mx = max(mx,length(p-a));
mx = max(mx,length(p-b));
}
int main()
{
cin>>t;
for( int cas = 1;cas<=t;++cas)
{
cin>>anum>>bnum;
double av=0.0,bv=0.0;
ap[0].read();
for( int i = 1 ; i <anum;++i)
{
ap[i].read();
av += length(ap[i]-ap[i-1]);
}
bp[0].read();
for( int i = 1 ;i <bnum;++i)
{
bp[i].read();
bv += length(bp[i]-bp[i-1]);
}
int sa,sb;
sa = sb = 0;
point pa=ap[0],pb=bp[0];//当前点
mi = 1e9;
mx = -1e9;
while( sa<anum-1 && sb<bnum-1)
{
double alen = length( ap[sa+1]-pa);//当前点到下一拐点的距离
double blen = length( bp[sb+1]-pb);
double t = min( alen/av,blen/bv);
//当某一只狗率先到达拐点时,两只狗的位移
vec awalk = ( ap[ sa+1]-pa)/alen * t *av;
vec bwalk = ( bp[ sb+1]-pb)/blen * t *bv;
//更新当前最大值,最小值 再更新当前点
update( pa,pb,pb+bwalk-awalk);
/*
狗A,狗B同时奔跑。
可以将狗A看做静止,狗B以 (bv - av)的速度奔跑。
*/
pa = pa+awalk;
pb = pb+bwalk;
if( pa==ap[sa+1])sa++;
if( pb==bp[sb+1])sb++;
}
printf("Case %d: %.0lf\n",cas,mx-mi);
}
return 0;
}