アットウィキロゴ

全体公開 > 合同練習会 > 20130323 > F 頑固なヌーRick

問題の概要

Rickたちヌーの群れが, ある方角FSを目指している.
FSに向かうにあたり, いくつかの餌場があり, それらを直線でつないだ経路で進む.
経路の隣合う餌場は, 距離がd以下でなければならない.
また, 餌場では90度より向きを変えてはならない.
更に, 常にFSの方角から90度以下を向いていなければならない.
これらの条件を満たす餌場のうち, 変える向きが最小な所に向かう.
この時, Rickたちはどのように動くだろうか.

実装の方針, 注意点

+ ...
(符号無し)角度の大小 <=> cosの大小の逆
であり, 90度との比較は正負でわかる為, cos で処理する.
また, 念の為, 比較は小さい正数EPSを噛ませて行った.

ソースコード

+ ...
  1. typedef complex<double> P;
  2. #define X real()
  3. #define Y imag()
  4. double dot(P a, P b){
  5. return (a * conj(b)).X;
  6. }
  7. double dist(P a, P b){
  8. return abs(a - b);
  9. }
  10. double costheta(P a, P b){
  11. a /= abs(a);
  12. b /= abs(b);
  13. return dot(a, b);
  14. }
  15. bool solve(){
  16. P fs;
  17. cin >> fs.X >> fs.Y;
  18. int n; cin >> n;
  19. int s; cin >> s;
  20. double d; cin >> d;
  21. if(!n) return false;
  22.  
  23. vector<P> in(n);
  24. rep(i, n) cin >> in[i].X >> in[i].Y;
  25.  
  26. --s;
  27. P dir = fs;
  28.  
  29. vector<int> res(1, s);
  30. while(true){
  31. pair<double, int> nex(-INF, -1);
  32. rep(i, n) if(i != s) if(dist(in[s], in[i])-EPS < d){
  33. if(costheta(dir, in[i]-in[s]) < EPS) continue;
  34. double c = costheta(in[i]-in[s], fs);
  35. if(c < EPS) continue;
  36. maxeq(nex, make_pair(c, i));
  37. }
  38. if(nex.snd == -1) break;
  39. int t = nex.snd;
  40. dir = in[nex.snd] - in[s];
  41. s = nex.snd;
  42. res.pb(s);
  43. }
  44. repsz(i, res){
  45. if(i) cout << " ";
  46. cout << res[i]+1;
  47. }
  48. cout << endl;
  49. return true;
  50. }
  51.  



最終更新:2013年03月27日 00:17