これ幾何としてはライブラリもいらないしさほど難しくないと思うんだけど、なんでこんな正解者少ないんだろう…。
https://atcoder.jp/contests/ddcc2019-final/tasks/ddcc2019_final_c
問題
円形のフィールド内に、さらに円柱が1個ある。
フィールド中、円柱外に光源があるとする。光源から出た光は基本的に直進するが、途中任意の位置で任意の角度に向きを変える、ということがK回まで行える。
照らされるフィールドの外壁の割合を求めよ。
解法
光源から、円柱の左側に接するように進み、外周スレスレで再度同様に向きを変える、という光と、逆に右側に接するように進む光を考えればよい。
線分と円の交差判定は二次方程式を解いてもよいが、以下では二分探索で横着している。
double LX[11],LY[11]; double RX[11],RY[11]; double PX,PY,PR,SX,SY; int K; double angle(double ax,double ay,double bx,double by) { double ret=atan2(by,bx)-atan2(ay,ax); ret/=8*atan(1); if(ret<0) ret+=1; return ret; } pair<double,double> hoge(double X,double Y,int dir) { double r=hypot(X-PX,Y-PY); double deg=atan2(PY-Y,PX-X)+dir*asin(PR/r); double dx=cos(deg); double dy=sin(deg); int i; double di=2; FOR(i,100) { double nx=X+di*dx; double ny=Y+di*dy; if(ny*ny+nx*nx<=1) { X=nx; Y=ny; } di/=2; } return {X,Y}; } void solve() { int i,j,k,l,r,x,y; string s; cin>>PX>>PY>>PR; cin>>SX>>SY>>K; auto a=hoge(SX,SY,1); LX[0]=a.first,LY[0]=a.second; a=hoge(SX,SY,-1); RX[0]=a.first,RY[0]=a.second; double ret=angle(LX[0],LY[0],RX[0],RY[0]); _P("%.12lf\n",min(1.0,ret)); FOR(i,K) { a=hoge(LX[i],LY[i],1); LX[i+1]=a.first,LY[i+1]=a.second; a=hoge(RX[i],RY[i],-1); RX[i+1]=a.first,RY[i+1]=a.second; ret+=angle(LX[i+1],LY[i+1],LX[i],LY[i]); ret+=angle(RX[i],RY[i],RX[i+1],RY[i+1]); _P("%.12lf\n",min(1.0,ret)); } }
まとめ
幾何はライブラリがないときつい、みたいな先入観があるのかな…?