Gym 100339A Bike Roads

Andrew Stankevich Contest 23
Petrozavodsk, February 1, 2007

Problem A. Bike Roads

Andrew lives at countryside. The area he lives at has two bike roads, each of which has the form of acircle with radius r. Roads have no common points.
Andrew’s house is located at one of the roads, and his school is located at the other one. Each day Andrew rides his bike from home to school and back. He has noticed that riding along the road is easier than riding by the ground. When riding along the road Andrew’s speed is u, and when riding by the ground his speed is v. Now Andrew wonders what minimal time he needs to get from his house to school.
Let us introduce the coordinate system so that the center of the bike road where Andrew’s house is located were (0, 0), and the center of the bike road where his school is located were (0, d). The radius of each road is r. Andrew’s house is located at a point (x1, y1), and his school is located at a point (x2, y2). His speed by the road is u, and his speed by the ground is v.


Input
Input file contains eight floating point numbers: d, r, x1, y1, x2, y2, u and v (1 ≤ r ≤ 100, 2r < d ≤ 100,1 ≤ v < u ≤ 10). All equalities are up to 10−9
.
Output
Output one floating point number — the minimal time Andrew needs to get from his house to school.
Your answer must be accurate up to 10−6
.
Example


20 5
5 0 5 20
2 1


16.5757337181


20 5
-5 0 5 20
2 1


17.2040517249

解题思路:

三分套三分

将两个圆进行分块,分块表示两个圆之间连线的出发点和进入点的位置

在每一块内进行三分套三分的操作

三分角度,维护最短时间


分8*8个区域直接三分

<pre name="code" class="cpp">//      whn6325689
//		Mr.Phoebe
//		http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")


using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;

#define CLR(x,y) memset(x,y,sizeof(x))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))
#define MID(x,y) (x+((y-x)>>1))
#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1;
    char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------


double D, R, X1, Y1, X2, Y2, U, V;

inline double sqr(double x)
{
    return x * x;
}

inline double calc2(double a, double b)
{
    double xx1 = X1 * cos(a) + Y1 * sin(a);
    double yy1 = -1.0 * X1 * sin(a) + Y1 * cos(a);
    double xx2 = X2 * cos(b) + (Y2-D) * sin(b);
    double yy2 = -1.0 * X2 * sin(b) + (Y2-D) * cos(b) + D;
    return fabs(b)*R / U + sqrt(sqr(yy2 - yy1) + sqr(xx2 - xx1)) / V;
}

inline double threeB(double a, double l, double r)
{
    while (r - l > eps)
    {
        double ml = (l + r) / 2.0;
        double mr = (ml + r) / 2.0;
        if (calc2(a, ml) > calc2(a, mr))
            l = ml;
        else
            r = mr;
    }
    return calc2(a, l);
}

inline double calc(double a)
{
    double ans1 = threeB(a, -PI, -0.75 * PI);
    double ans2 = threeB(a, -0.75 * PI, -0.5 * PI);
    double ans3 = threeB(a, -0.5 * PI, -0.25 * PI);
    double ans4 = threeB(a, -0.25 * PI, 0.0);
    double ans5 = threeB(a, 0.0, 0.25 * PI);
    double ans6 = threeB(a, 0.25 * PI, 0.5 * PI);
    double ans7 = threeB(a, 0.5 * PI, 0.75 * PI);
    double ans8 = threeB(a, 0.75 * PI, PI);

    double ans = min(ans1, min(ans2, min(ans3, min(ans4, min(ans5, min(ans6, min(ans7, ans8)))))));
    return fabs(a)*R / U + ans;
}

inline double threeA(double l, double r)
{
    while (r - l > eps)
    {
        double ml = (l + r) / 2.0;
        double mr = (ml + r) / 2.0;
        if (calc(ml) > calc(mr))
            l = ml;
        else
            r = mr;
    }
    return calc(l);
}

inline void solve()
{
    double ans1 = threeA(-PI, -0.75 * PI);
    double ans2 = threeA(-0.75 * PI, -0.5 * PI);
    double ans3 = threeA(-0.5 * PI, -0.25 * PI);
    double ans4 = threeA(-0.25 * PI, 0.0);
    double ans5 = threeA(0.0, 0.25 * PI);
    double ans6 = threeA(0.25 * PI, 0.5 * PI);
    double ans7 = threeA(0.5 * PI, 0.75 * PI);
    double ans8 = threeA(0.75 * PI, PI);

    double ans = min(ans1, min(ans2, min(ans3, min(ans4, min(ans5, min(ans6, min(ans7, ans8)))))));
    printf("%.10lf\n", ans);
}

int main()
{
    freopen("bike.in", "r", stdin);
    freopen("bike.out", "w", stdout);
    while (~scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &D, &R, &X1, &Y1, &X2, &Y2, &U, &V))
    {
        solve();
    }
    return 0;
}

 

按照S菊苣所说,思路比较扭曲

这里考虑的是与Y轴的夹角,所以比较不好理解

分块比较好懂,真是因为分块简洁,才导致了必须用于Y轴的夹角

//      whn6325689
//		Mr.Phoebe
//		http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")


using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;

#define CLR(x,y) memset(x,y,sizeof(x))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))
#define MID(x,y) (x+((y-x)>>1))
#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1; char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------

struct Point
{
	double x,y;
	Point(double xx=0.0,double yy=0.0):x(xx),y(yy){	}
}s,t;

double d,r,u,v;

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 arc(double a,double b)
{
    return min(abs(a-b),2*PI-abs(a-b));
}

double school(double l,double h,Point s)
{
	double a=atan2(t.x,t.y-d);
    while(h-l>eps)
	{
        double mid=(l+h)/2;
        double midd=(mid+h)/2;
        Point t1(r*sin(mid),d+r*cos(mid));
        Point t2(r*sin(midd),d+r*cos(midd));
        double le=dist(s,t1)/v+r*arc(a,mid)/u;
        double ri=dist(s,t2)/v+r*arc(a,midd)/u;
        if(le<ri)
			h=midd;
        else
			l=mid;
    }
    Point t1(r*sin(l),d+r*cos(l));
    return dist(s,t1)/v+r*arc(a,l)/u;
}

double out(Point s)
{
	double a=atan2(t.x,t.y-d);
	double b=-atan2(s.x,d-s.y);
	if(a<=b)
	{
		double ans=min(school(a,b,s),school(-PI,a,s));
		return min(ans,school(-PI+b,-PI,s));
	}
	else if(a>b && a<=0)
    {
        double ans=min(school(b,a,s),school(a,0,s));
        return min(ans,school(0,PI+b,s));
    }
	else if(a-b-PI<=0 && a>=0)
	{
		double ans=min(school(b,0,s),school(0,a,s));
		return min(ans,school(a,PI+b,s));
	}
	else
	{
		double ans=min(school(PI,2*PI+b,s),school(a,PI,s));
		return min(ans,school(PI+b,a,s));
	}
}

double home(double l,double h)
{
    double a=atan2(s.x,s.y);
    while(h-l>eps)
	{
        double mid=(l+h)/2;
        double midd=(mid+h)/2;
        double le=out(Point(r*sin(mid),r*cos(mid)))+r*arc(a,mid)/u;
        double ri=out(Point(r*sin(midd),r*cos(midd)))+r*arc(a,midd)/u;
        if(le<ri)
            h=midd;
        else
			l=mid;
    }
    return out(Point(r*sin(l),r*cos(l)))+r*arc(a,l)/u;
}

int main()
{
	freopen("bike.in","r",stdin);
	freopen("bike.out","w",stdout);
	scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&d,&r,&s.x,&s.y,&t.x,&t.y,&u,&v);
	if(s.x<0)
        s.x=-s.x,t.x=-t.x;
    double a=atan2(s.x,s.y);
	double ans=min(home(0,a),home(a,PI));
	ans=min(ans,home(-PI+a,0));
	ans=min(ans,home(-PI,-PI+a));
	printf("%.10f\n",ans);
	return 0;
}


最早我是将第一步的分块分成(0,PI/2) (PI/2,PI) (-PI,-PI/2) (-PI/2,0)

但是这样是不足的,所以才导致了第二份代码的扭曲

若将第一步分成八块,则可以

//      whn6325689
//		Mr.Phoebe
//		http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")


using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;

#define CLR(x,y) memset(x,y,sizeof(x))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))
#define MID(x,y) (x+((y-x)>>1))
#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1; char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------

struct Point
{
	double x,y;
	Point(double xx=0.0,double yy=0.0):x(xx),y(yy){	}
}s,t;

double d,r,u,v;

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 arc(double a,double b)
{
    return min(abs(a-b),2*PI-abs(a-b));
}

double school(double l,double h,Point s)
{
	double a=atan2(t.y-d,t.x);
    while(h-l>eps)
	{
        double mid=(l+h)/2;
        double midd=(mid+h)/2;
        Point t1(r*cos(mid),d+r*sin(mid));
        Point t2(r*cos(midd),d+r*sin(midd));
        double le=dist(s,t1)/v+r*arc(mid,a)/u;
        double ri=dist(s,t2)/v+r*arc(midd,a)/u;
        if(le<ri)
			h=midd;
        else
			l=mid;
    }
    Point t1(r*cos(l),d+r*sin(l));
    return dist(s,t1)/v+r*arc(l,a)/u;
}

double out(Point s)		//出点
{
	double a=atan2(t.y-d,t.x);
	double b=-atan2(d-s.y,s.x);
	if(a<=b)
	{
		double ans=min(school(a,b,s),school(-PI,a,s));
		return min(ans,school(-PI+b,-PI,s));
	}
	else if(a>b && a<=0)
    {
        double ans=min(school(b,a,s),school(a,0,s));
        return min(ans,school(0,PI+b,s));
    }
	else if(a-b-PI<=0 && a>=0)
	{
		double ans=min(school(b,0,s),school(0,a,s));
		return min(ans,school(a,PI+b,s));
	}
	else
	{
		double ans=min(school(PI,2*PI+b,s),school(a,PI,s));
		return min(ans,school(PI+b,a,s));
	}
}

double home(double l,double h)
{
	double a=atan2(s.y,s.x);
    while(h-l>eps)
	{
        double mid=(l+h)/2;
        double midd=(mid+h)/2;
        double le=out(Point(r*cos(mid),r*sin(mid)))+r*arc(a,mid)/u;
        double ri=out(Point(r*cos(midd),r*sin(midd)))+r*arc(a,midd)/u;
        if(le<ri)
            h=midd;
        else
			l=mid;
    }
    return out(Point(r*cos(l),r*sin(l)))+r*arc(a,l)/u;
}

int main()
{
	freopen("bike.in","r",stdin);
 	freopen("bike.out","w",stdout);
	scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&d,&r,&s.x,&s.y,&t.x,&t.y,&u,&v);
	double ans=min(home(0,PI/4),home(PI/4,PI/2));
	ans=min(ans,home(PI/2,3*PI/4));
	ans=min(ans,home(3*PI/4,PI));

	ans=min(ans,home(-PI,-3*PI/4));
	ans=min(ans,home(-3*PI/4,-PI/2));
	ans=min(ans,home(-PI/2,-PI/4));
	ans=min(ans,home(-PI/4,0));
	printf("%.10f\n",ans);
	return 0;
}


第三份代码是由第一份的第一步和第二份的第二步进行合并而成的

因此分块的方案有很多,组合也特别多

希望大家自己思考出自己的分块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值