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; }
第三份代码是由第一份的第一步和第二份的第二步进行合并而成的
因此分块的方案有很多,组合也特别多
希望大家自己思考出自己的分块