模擬地区予選2010 F.Two-Wheel Buggy
AOJに投げてみたらコードサイズがだいぶ小さかったので晒してみます。
嘘の告発は大歓迎です。
解法
- 直進か曲がるかの2通りに場合分けして処理する
- 車の状態は,2個のタイヤの中点pと車の方向dirによって管理
- 直進(左右の回転数が一緒)はやるだけ
- 向いてる方向にまっすぐ進める
- 曲がる(左右の回転数が違うとき)ときは以下の通り
- pの回転中心cは2つのタイヤの中心を結ぶ直線上にある
- 左右のタイヤが描く円周の長さの比から式を立てると、
- c = p + P(cos(dir-pi/2), sin(dir-pi/2))*(L+R)/(L-R)*D となる
- これはL,Rの正負によらず同じ式。
- ちなみにL==R(直進)だと回転半径が無限大という扱い
- 後は回転数から回転角を求めて車を移動させる
#include <iostream> #include <fstream> #include <complex> #include <cmath> #include <stdio.h> using namespace std; typedef complex<double> P; const double PI = acos(-1.0); int main(){ int N, D; ifstream fin("F.txt"); while(fin >> N >> D, N){ P p = P(0,0); double dir = PI/2; for(int i=0;i<N;i++){ int L, R, T; fin >> L >> R >> T; if(L==R){ p = p + T*L/180.0*PI*P(cos(dir), sin(dir)); } else { double r = ((double)L+R)/(L-R)*D; P c = p + P(cos(dir), sin(dir))*P(0,-1)*r; double agl = (r > 0 ? -L/abs(r+D) : R/abs(r-D))*T*PI/180.0; dir += agl; p = (p-c)*P(cos(agl), sin(agl))+c; } } printf("%.8lf\n%.8lf\n", real(p), imag(p)); } }