Description
Input
The input consists of several test cases.
The first line consists of one integer T (T <= 30), meaning the number of test cases.
For each test cases:
The first line consists of integer n (n<=10).
In the next n lines, the i-th line consists of four real number, xi, yi, ri, ui, describing the motion of each sheep (|xi|, |yi| <= 100, 0<=ri<=100, 0<ui<1). (xi, yi) means the coordinate of the center of the circle, ri means the radius of the circle, and ui means the speed of the sheep i.
You should know Anny always started in (0,0). And the sheep always started in (xi+ri, yi).
Output
For each test case, output one line with one real number with 6 decimal places meaning the minimum time Anny could leave without any space.
Sample Input
1 1 11 0 1 0.31415926535897932384626433832795
Sample Output
10.000000
本题的难点是根据当前坐标和时间求与第i只羊的最短交汇时间,转移的耗时显然是满足二分性质的,知道当前位置,当前时刻,下一只羊的信息就能够通过二分求得耗时
状态压缩Dp,dp[status][i]表示抓了status状态表示的羊最后抓的羊的编号为i
其实用爆搜应该也可以
时间复杂度:?(??^2∗2^?)(k是二分迭代次数)
#include<iostream> #include<stdio.h> #include<math.h> using namespace std; typedef struct{ double x,y,time; bool isCal; }Status; typedef struct{ double x,y,r,u; }Point; Status f[1<<11][10]; Point p[10]; int t,n; Status calcuateTimeAndXY(double x,double y,double time,int num){ double left=0,right=1000,mid; double u=p[num].u; double r=p[num].r; double x0=p[num].x; double y0=p[num].y; double x2,y2; while(fabs(right-left)>1e-9) { mid=(right+left)/2.0; double t=mid+time; double theta=(u*t-floor(u*t/(2*M_PI*r))*2*M_PI*r)/r; x2=x0+r*cos(theta); y2=y0+r*sin(theta); if((x2-x)*(x2-x)+(y2-y)*(y2-y)>mid*mid) left=mid; else right=mid; } Status a; a.x=x2;a.y=y2;a.time=time+mid;a.isCal=true; return a; } void Dp(int state,int num){ if(f[state][num].isCal==true) return ; if(state==0){f[state][num]=calcuateTimeAndXY(0,0,0,num);return ;} double minTime=1e100; for(int i=0;i<n;++i) if((state&(1<<i))!=0) { Dp(state^(1<<i),i); Status tt=calcuateTimeAndXY(f[state^(1<<i)][i].x,f[state^(1<<i)][i].y,f[state^(1<<i)][i].time,num); if(tt.time<minTime) { minTime=tt.time; f[state][num]=tt; } } return ; } int main() { scanf("%d",&t); while(t>0) { t--; scanf("%d",&n); for(int i=0;i<n;++i) scanf("%lf %lf %lf %lf",&p[i].x,&p[i].y,&p[i].r,&p[i].u); for(int i=0;i< 1<<n ;++i) for(int j=0;j<n;++j) f[i][j].isCal=false; double ans=1e100; for(int i=0;i<n;++i) { Dp(((1<<n) -1)^(1<<i),i); if(f[((1<<n) -1)^(1<<i)][i].time<ans) ans=f[((1<<n) -1)^(1<<i)][i].time; } // cout<<f[0][0].time<<" "<<f[0][1].time<<endl; printf("%.6f\n",ans); } }