uva11796 Dog Distance


C

Dog Distance

Input

Standard Input

Output

Standard Output

Two dogs, Ranga and Banga, are running randomly following two different paths. They both run for T seconds with different speeds. Ranga runs with a constant speed of Rm/s, whereas Banga runs with a constant speed of S m/s. Both the dogs start and stop at the same time. Let D(t) be the distance between the two dogs at time t.

The dog distance is equal to the difference between the maximum and the minimum distance between the two dogs in their whole journey.

 

Mathematically,

Dog Distance = {max (D(a)) 0 <= a <= T} – {min (D(b))  0 <= b <= T}

Given the paths of the two dogs, your job is to find the dog distance.

Each path will be represented using N points, (P1 P2 P3 ... PN). The dog following this path will start from P1and follow the line joining with P2, and then it will follow the line joining P2-P3, then P3-P4 and so on until it reaches Pn.

Input

Input starts with an integer I(I≤1000), the number of test cases.

Each test case starts with 2 positive integers A(2≤A≤50),B(2≤B≤50). The next line contains the coordinates ofA points with the format XYXY2 ...XA YA(0≤Xi,Yi≤1000). These points indicate the path taken by Ranga. The next line contains B points in the same format. These points indicate the path taken by Banga. All distance units are given in meters and consecutive points are distinct. All the given coordinates are integers.

Note that the values of TR and S are unknown to us.

Output

For each case, output the case number first. Then output the dog distance rounded to the nearest integer. Look at the samples for exact format.

 

 

Sample Input

Sample Output

2

2 2

0 0 10 0

0 1 10 1

3 2

635 187 241 269 308 254

117 663 760 413

 

Case 1: 0

Case 2: 404

 



大概意思是有a,b两条狗。同时出发,同时停止,他们的行驶路径不一样,速度也不一样。然后分别给出他们路径上的拐角点,然后沿直线跑。问他们最大距离与最小距离之差是多少。

因为a,b是同时出发,同时达到,但是他们的速度不一定一样,所以我们可以设他们的速度为La,Lb(La,Lb为a,b狗的总路程)

那么,如何a,b都是沿着直线运动的时候如何求他们之间的最短最长距离呢?

因为运动都是相对的,所以我们可以把a看成不懂的,而b相对于a的移动方向就是Vb - Va,因此就可以看成a和线段 b + (Vb -Va)之间的关系了

至于方向Va,Vb向量怎么求,我们可以利用单位向量 X 移动时间 X 移动速度 得到。

http://blog.csdn.net/u013451221/article/details/38982741

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<functional>
#define eps 1e-9
#include<vector>
using namespace std;
const double PI = acos(-1.0);
int dcmp( double x ){ if( abs(x) < eps ) return 0;else return x < 0?-1:1; }
struct point{
    double x,y;
    point( double x = 0,double y = 0 ):x(x),y(y){}
}node[1000]; 
typedef point Vector;
struct segment{
    point a,b;  segment(){}
    segment(point _a,point _b){a=_a,b=_b;}
};
struct circle{
    point c; double r;  circle(){}
    circle(point _c, double _r):c(_c),r(_r) {}
    point  PPP(double a)const{return point(c.x+cos(a)*r,c.y+sin(a)*r);}
};
struct line{
    point p,v; double ang;
    line() {}
    line( const point &_p, const point &_v):p(_p),v(_v){ang = atan2(v.y, v.x);}
    inline bool operator < (const line &L)const{return  ang < L.ang;}
};
point operator + (point a,point b){return point( a.x + b.x,a.y + b.y );}
point operator - (point a,point b){return point( a.x - b.x,a.y - b.y );}
point operator * (point a,double b){return point( a.x*b,a.y*b );}
point operator / (point a,double b){ return point( a.x/b,a.y/b );}
bool  operator <  (const point &a, const point &b ){return  a.x <  b.x || (a.x == b.x && a.y < b.y );}
bool  operator == (const point &a, const point &b ){return (dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0 );}
bool  operator != (const point &a,const point &b ){return a == b?false:true;}

double Dot( point a,point b ){return a.x*b.x + a.y*b.y;} // 点到点的距离  //点积 ab=|a||b|cos@
double Dist(point A,point B){return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));}
double Length( point a ){return sqrt( Dot( a,a ) );}    // 向量长度
double Angle( point a,point b ){ return acos( Dot(a,b)/Length(a)/Length(b) );} // 两个向量的角度
double D_T_D(const double ° ){ return deg/180.0*PI; }

// 向量旋转 rad 度数 rad>0逆时针,rad<0顺时针
point Rotate( point a, double rad ){
     return point( a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad) );
}
// 向量的 法线向量 的单位向量 ==向量逆时针旋转90度
point Normal( point a ){
     double L = Length(a); 
	 return point(-a.y/L,a.x/L);
}
// 叉积计算   a*b=|a||b|sin@;
double Cross( point a,point b ){
    return a.x*b.y - a.y*b.x;
}
// 获取 两个向量叉积  
double get_Mix( point a,point b,point pot ){
    a.x = a.x - pot.x; a.y = a.y - pot.y;
    b.x = b.x - pot.x; b.y = b.y - pot.y;
    return Cross( a,b );
}
// 直线相交求交点
point get_line_inter( point p,point v, point q,point w ){
    point u = p - q;
    double t = Cross(w,u)/Cross(v,w);
    return p+v*t;
}
// p点到直线 的距离
double dis_p_line( point p,point a,point b ) {
    point v1 = b-a, v2 = p-a;
    return abs( Cross(v1,v2)/Length(v1) );
}
//点在直线上的投影
inline point GetLineProjection(const point &p,const point &a,const point &b){
    point v=b-a;
    return a+v*(Dot(v,p-a)/Dot(v,v));
}
// 点到线段的距离
double dis_p_segm( point p,point a,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);
    if( dcmp(Dot(v1,v3)) > 0 ) return Length(v3);
    return fabs(Cross( v1,v2 ))/Length(v1);
}
//海伦公式 三条边
double Heron(double a,double b,double c){
    double p=(a+b+c)/2;
    return sqrt(p*(p-a)*(p-b)*(p-c));
}
// 多边形面积 从p[0] 开始,p[n] 结束
double ploy_area( vector<point>p,int n ){
    double area = 0;
    n=p.size();
    for( int i = 1; i < n-1; i++ )
       area += Cross( p[i]-p[0],p[i+1]-p[0] );
    return area/2.0;
}
// 线段相交判断 先必须去掉不相交的状态;再判断方向
bool get_set(const point& a1, const point& a2, const point& b1, const point& b2) {
  double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
  c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
  return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
// 线段 直线 平行判断只需要对应向量平行;
bool get_pall( point a,point b,point c,point d ){
    if( Cross( a-b,c-d ) == 0 )return true;
    return false;
}
// 直线  重合判断 只需要 一条直线的两点都在直线方向
bool get_doub( point a,point b,point c,point d ){
    if( Cross( d-b,a-b ) == 0 && Cross( c-b,a-b ) == 0 )return 1;
    return 0;
}
// 获取 线段 交点;依据 叉积判断
point get_pot( point a,point b,point c,point d ){
    point temp;
    temp.x = ( c.x*Cross(b-a,d-a) - d.x*Cross(b-a,c-a) )/( Cross(b-a,d-a) - Cross(b-a,c-a) );
    temp.y = ( c.y*Cross(b-a,d-a) - d.y*Cross(b-a,c-a) )/( Cross(b-a,d-a) - Cross(b-a,c-a) );
    return temp;
}
//获取直线的交点  同时也可以是线段的交点;
point get_ppp( point a,point b,point c,point d ){
    double a0 = a.y - b.y; double b0 = b.x - a.x; double c0 = a.x*b.y - b.x*a.y;
    double a1 = c.y - d.y; double b1 = d.x - c.x; double c1 = c.x*d.y - d.x*c.y;
    double D =  a0*b1 - a1*b0; point temp;
    temp.x = ( b0*c1 - b1*c0 )/D;
    temp.y = ( a1*c0 - a0*c1 )/D;
    return temp;
}
//点pot 是否 在线段 ab 上 只需 叉积等于0  点积等于0
bool online( point a,point b,point pot ){
    if( Cross( a - pot,b - pot ) == 0 && Dot( a - pot,b - pot ) <= 0 )return 1;
    return 0;
}
//p为点,poly为多边形 点在多边形内判定
int isPointInPolygon(const point& p, const vector<point> poly){
  int n = poly.size();
  int wn = 0;
  for(int i = 0; i < n; i++){
    const point& p1 = poly[i];
    const point& p2 = poly[(i+1)%n];
    if(p1 == p || p2 == p || online(p1, p2, p)) return -1; 
    int k = dcmp(Cross(p2-p1, p-p1));
    int d1 = dcmp(p1.y - p.y);
    int d2 = dcmp(p2.y - p.y);
    if(k > 0 && d1 <= 0 && d2 > 0) wn++;
    if(k < 0 && d2 <= 0 && d1 > 0) wn--;
  }
  if (wn != 0) return 1; //内部 
  return 0; //外部 
}
int top,res[1123456]; // 凸包 ( 起点 0 ) ( n 个点 ) 自己写的,,需要改进 改进;
void GRA( int n )
{
    sort( node,node+n ); // 先排序
    top = 1; res[0] = 0; res[1] = 1;// 从第0位开始放;前两位不管
    for( int i = 2; i <= n; i++ ){
        while( top  && get_Mix( node[i],node[res[top]],node[res[top-1]] ) > 0 )top--;
        res[++top] = i;
    }
    int k = top;
    for( int i = n-2; i >=  0; i-- ){
        while( top > k && get_Mix( node[i],node[res[top]],node[res[top-1]] ) > 0 )top--;
        res[++top] = i;
    }
    top--; // 会添加进去最后一个点
}
//求两圆相交
int C_T_C( circle c1,circle c2,point &p1,point &p2 ){
    double d = Length( c1.c- c2.c );
    if( dcmp( d ) == 0 ) {
        if( dcmp( c1.r-c2.r ) == 0 ) return -1;//两圆重合
        return 0;
    }
    if( dcmp( c1.r + c2.r - d ) < 0 ) return 0;
    if( dcmp( fabs( c1.r - c2.r ) - d ) > 0 ) return 0;
    double a = Angle( c2.c - c1.c,point( 1,0 ) );
    double da = acos(( c1.r * c1.r + d * d - c2.r * c2.r )/( 2 * c1.r * d ) );
    p1 = c1.PPP( a - da ); p2 = c1.PPP( a + da );
    if( p1 == p2 ) return 1;
    return 2;
}
//圆与直线交点 返回交点个数
int C_T_L( line L,circle C,point &p1,point &p2){
    double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y-C.c.y;
    double e = a*a + c*c, f = 2*(a*b+c*d), g = b*b + d*d -C.r*C.r;
    double delta = f*f - 4*e*g;
    if( dcmp(delta) < 0 )  return 0;//相离
    if( dcmp(delta) == 0 ) {//相切
        p1 = p1 = L.p + L.v*( -f/(2*e) );
        return 1;
    }//相交
    p1 = ( L.p + L.v * ( -f-sqrt(delta) )/( 2*e ) );
    p2 = ( L.p + L.v * ( -f+sqrt(delta) )/( 2*e ) );
    return 2;
}
//点与圆的切线;
int get_P_C_inter( point p,circle c, point *v )
{
    point u = c.c - p; double dist = Length(u);
    if( dist < c.r )return 0;
    else if( dcmp( dist - c.r) == 0 ){
        v[0] = Rotate( u,PI/2 );
        return 1;
    }else {
        double ang = asin( c.r/dist );
        v[0] = Rotate(u,-ang);
        v[1] = Rotate(u,+ang);
        return 2;
    }
    return -1;
}
//判断点d是否在三角形a,b,c内 
bool inthree(const point a,const point b,const point c,const point d)
{
	point A,B,C;
	A=a-d;
	B=b-d;
	C=c-d;
	double s,s1;
	s=Cross(A,B)/2+Cross(A,C)/2+Cross(B,C)/2;
	s1=Cross(c-b,a-b)/2;
	if (fabs(s-s1)<eps) return true;
	else return false;
}
int na,nb;
double la,lb;
double Min,Max;
point pa[100],pb[100];
void update(point p,point a,point b)
{
	Min=min(Min,dis_p_segm(p,a,b));
	Max=max(Max,Length(p-a));
	Max=max(Max,Length(p-b));
}
double go()
{
	point psa=pa[0];
	point psb=pb[0];
	for (int nxta=0,nxtb=0;nxta<na-1 && nxtb<nb-1;)
	{
		double ta=Dist(pa[nxta+1],psa); //a到下一个拐点的距离 
		double tb=Dist(pb[nxtb+1],psb);
		double t=min(ta/la,tb/lb);  //最短时间
		Vector va=(pa[nxta+1]-psa)/ta*la*t;
		Vector vb=(pb[nxtb+1]-psb)/tb*lb*t;
		update(psa,psb,psb+vb-va);
		psa=psa+va;
		psb=psb+vb;
		if (psa==pa[nxta+1]) nxta++;
		if (psb==pb[nxtb+1]) nxtb++;
	}
	return Max-Min;
}
int main()
{
	int T,cas=1;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d%d",&na,&nb);
		la=0;lb=0;
		Min=1e20;
		Max=0;
		for (int i=0;i<na;i++)
		{
			scanf("%lf%lf",&pa[i].x,&pa[i].y);
			if (i>0) la+=Length(pa[i]-pa[i-1]);
		}
		for (int i=0;i<nb;i++)
		{
			scanf("%lf%lf",&pb[i].x,&pb[i].y);
			if (i>0) lb+=Length(pb[i]-pb[i-1]);
		}
		printf("Case %d: %.0lf\n",cas++,go());
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值