Dog Distance UVA - 11796

思路:对甲乙,看谁先到达拐点。分析从之前的位置到拐点的位置两者的运动过程,那么这个过程中两者都做的直线运动,而且运动是相对的,则把甲看成静止的,乙做相对运动。更新出在这个过程中的最大值和最小值。并更新甲乙经过此轮运动后所在位置。然后再找谁先到拐点。。。。直到到末位置为止。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cassert>
#define inf 0x3f3f3f3f
using namespace std;
struct Point {
    double x, y;
    Point (double x=0, double y=0):x(x), y(y){}
};
bool operator <(const Point&a,const Point&b){//从小到大排序
    return a.x<b.x || (a.x==b.x&&a.y<b.y);
}
typedef Point Vector;
//重载向量间的加减乘除
Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p){ return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p){ return Vector(A.x/p, A.y/p); }
Point read_point(){//读入点
    Point p;
    scanf("%lf%lf", &p.x, &p.y);
    return p;
}
const double eps=1e-10;//判断浮点数和0的关系
int dcmp(double x){
    if(fabs(x)<eps)return 0;
    else 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 Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y; }//A,B点乘
double Length(Vector A){ return sqrt(Dot(A, A)); }//求向量长度

double Cross(Vector A, Vector B){//叉乘
    return A.x*B.y-A.y*B.x;
}
double DistanceTosegment(Point P,Point A,Point B){//点P到射线A,B的距离
    if(A==B)return Length(P-A);
    Vector v1=B-A;
    Vector 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);
}

Point P[100],Q[100];
double minn,maxn;
int T,A,B;
void update(Point P,Point A,Point B){
    minn=min(minn,DistanceTosegment(P, A, B));
    maxn=max(maxn,Length(P-A));
    maxn=max(maxn,Length(P-B));
}
int main(){
    scanf("%d",&T);
    int ca=1;
    while(T--){
        scanf("%d%d",&A,&B);
        for(int i=0;i<A;i++)
            P[i]=read_point();
        for(int i=0;i<B;i++)
            Q[i]=read_point();
        double len1=0,len2=0;
        for(int i=0;i<A-1;i++)
            len1+=Length(P[i+1]-P[i]);
        for(int i=0;i<B-1;i++)
            len2+=Length(Q[i+1]-Q[i]);
        int sa=0,sb=0;
        Point pa=P[0],pb=Q[0];
        minn=inf;maxn=-1*inf;
        while(sa<A-1&&sb<B-1){
            double La=Length(P[sa+1]-pa);
            double Lb=Length(Q[sb+1]-pb);
            double ti=min(La/len1,Lb/len2);//设总运动时间为1,则各自平均速度比len1,len2
            Vector Va=(P[sa+1]-pa)/La*ti*len1;
            Vector Vb=(Q[sb+1]-pb)/Lb*ti*len2;
            update(pa, pb, pb+Vb-Va);
            pa=pa+Va;
            pb=pb+Vb;
            if(pa==P[sa+1])sa++;
            if(pb==Q[sb+1])sb++;
        }
        printf("Case %d: %.0lf\n",ca++,maxn-minn);
    }
    return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值