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


狗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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值