アットウィキロゴ

全体公開 > 合同練習会 > 20130323 > C センサー付きロボット

問題の概要

次の3つの命令を受け付けるロボットが居る.
  • F: 前へ1単位進む.
  • R: 右へ90度回転する.
  • L: 左へ90度回転する.
但し, 壁があり, Fで壁に追突する場合は, 前に進む代わりに, 180度回転する.
壁はx, y軸のいずれかに平行に置かれ, 壁同士は接続され, 1つの多角形になっている.
壁, 初期位置, 命令が与えられるので, 最終位置と, ロボットの初期位置からの(ユークリッド)距離で最も離れた点を答えよ.
複数ある場合は, y座標の大きい方, それも複数あればx座標の大きい方.

実装の方針, 注意点

+ ...
座標や向きを, 複素数で管理する.
今の向きから, 右を向くには -i, 左を向くには i を掛ければよい.

出力の2つ目は, (初期位置からの距離の二乗, y座標, x座標) が辞書順で最も大きくなるような点.
距離そのままでも良いが, complex<int> では abs() は異なる動きをするので, 距離の二乗である norm() を用いる.

壁は, 壁である全ての点を set<P> に入れて管理した.
set<P> を使うため, 比較関数の実装が必要.
ついでに, 出力の2つ目を作るのが楽なように, (y座標, x座標) の辞書順で順序を入れた.
これにより, (初期位置からの距離の二乗, その点) が辞書順で大きいものを選べばよく, ''pair<int, P>'' で管理すると楽になる.

また, ''p(x1, y1)'' と ''q(x2, y2)'' を結ぶ壁は, x座標が区間 ''[min(x1, x2), max(x1, x2)]'', y座標が区間 ''[min(y1, y2), max(y1, y2)]'' に入る点全体である事に注意すると,
x軸に平行か, y軸に平行か, どちらが右/上にあるか等で場合分けせずに済む.

ソースコード

Not verified
+ ...
  1. typedef complex<int> P;
  2. #define X real()
  3. #define Y imag()
  4. namespace std{
  5. bool operator<(const P &p1, const P &p2){
  6. return p1.Y == p2.Y ? p1.X < p2.X : p1.Y < p2.Y;
  7. }
  8. };
  9. bool solve(){
  10. int n;
  11. cin >> n;
  12. if(!n) return false;
  13.  
  14. // 壁の生成
  15. vector<P> wall_raw(n);
  16. rep(i, n) cin >> wall_raw[i].X >> wall_raw[i].Y;
  17. set<P> wall;
  18. rep(i, n){
  19. P crr = wall_raw[i];
  20. P nex = wall_raw[(i+1)%n];
  21. REP(x, min(crr.X, nex.X), max(crr.X, nex.X)+1)
  22. REP(y, min(crr.Y, nex.Y), max(crr.Y, nex.Y)+1)
  23. wall.insert(P(x, y));
  24. }
  25.  
  26. P initial;
  27. cin >> initial.X >> initial.Y;
  28.  
  29. P pos = initial;
  30. P dir = P(0, 1);
  31. pair<int, P> res(0, initial);
  32. string s;
  33. cin >> s;
  34. repsz(i, s){
  35. if(s[i] == 'F'){
  36. if(wall.count(pos + dir)){
  37. // 反転
  38. dir *= -1;
  39. }else{
  40. // 直進
  41. pos += dir;
  42. }
  43. }else if(s[i] == 'R'){
  44. // 右回転
  45. dir *= P(0, -1);
  46. }else if(s[i] == 'L'){
  47. // 左回転
  48. dir *= P(0, 1);
  49. }
  50. maxeq(res, make_pair(norm(pos - initial), pos));
  51. }
  52. cout << pos.X << " " << pos.Y << " ";
  53. cout << res.snd.X << " " << res.snd.Y << endl;
  54. return true;
  55. }
  56.  



最終更新:2013年03月28日 14:34