UVA 11796 || Dog Distance ( 折线划分线段更新

来源:互联网 发布:ubuntu 命令行解压deb 编辑:程序博客网 时间:2024/06/07 07:01


狗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;}




0 0