本番にすべてのケースを考えきれなかった…。
http://community.topcoder.com/stat?c=problem_statement&pm=13184
問題
左右の座標0~Lからなる長さLの細い道路上にN匹の狼がおり、それぞれの初期位置とゴール位置が与えられる。
各狼をゴール位置に移動させたいが、細い道路上では他の狼とすれ違うことができない。
ただし、位置0及びLには広い空間があり、ここではすれ違いが可能である。
各狼をゴールに移動させる総移動距離を最小化せよ。
解法
あり得るケースは以下の2つである。
- 元々左側にいる狼x匹が位置0に移動してすれ違った後ゴールに移動し、右側にいるy匹が位置Lに移動してゴールに移動し、残りの真ん中の(N-x-y)匹は両端でのすれ違いを利用せずゴールに直行する。
- これが有効なのは、左x匹のゴール位置がそれぞれ左x番目までであり、右y匹のゴール位置が右y番目までであり、真ん中の(N-x-y)匹は開始位置とゴール位置における相対位置が維持できる場合である。
- xとyの取り方がO(N^2)で、後は移動距離の計算にO(N)なのでO(N^3)で計算できる。
- 一旦全員が位置0またはLに退避し、1体ずつ左右で移動してそれ以上すれ違う必要がなくなってから、それぞれゴール位置に移動する。
- 最初左側何匹が位置0に行くかをO(N)通り取れる。その後1体ずつの移動においてゴール位置が左側何匹目までは左に集まるかが同様にO(N)通り、移動距離の計算も合わせてO(N^3)で計算できる。
class NarrowPassage { public: int minDist(int L, vector <int> a, vector <int> b) { int i,x,y,j; int N=a.size(); pair<int,int> P[51]; int tar[51]; FOR(i,N) P[i]=make_pair(a[i],b[i]); sort(P,P+N); sort(b.begin(),b.end()); FOR(i,N) FOR(x,N) if(P[i].second==b[x]) tar[i]=x; int mi=1<<30,tot,ok; FOR(x,N+1) FOR(y,N+1) { if(x+y>N) continue; tot=0,ok=1; FOR(i,N) { if(i<x) tot+=P[i].first+P[i].second, ok &= tar[i]<x; else if(i>=x && i<N-y) tot+=abs(P[i].first-P[i].second) , ok &= tar[i]==i; else tot+=2*L-P[i].first-P[i].second , ok &= tar[i]>=N-y; } if(ok) mi=min(mi,tot); } FOR(x,N+1) FOR(y,N+1) { tot=0; FOR(i,N) { if(i<x) { if(tar[i]<y) tot+=P[i].first+P[i].second; else tot+=P[i].first+L+L-P[i].second; } else { if(tar[i]<y) tot+=L-P[i].first+L+P[i].second; else tot+=2*L-P[i].first-P[i].second; } } mi=min(mi,tot); } return mi; } }
まとめ
本番に移動経路を列挙できなかった…。
左端→右端に移動する狼と、右端→左端に移動する狼が同時に存在するケースが思い浮かばず。