SRM645 Div1 Med ArmyTeleportation
http://community.topcoder.com/stat?c=problem_statement&pm=13346
[問題]
平面上の整数座標にN個の出発点と、N個の目標点があり、全ての出発点を目標点に移動させる
。そのために、塔が3個ある。塔を使うと、全ての頂点を塔の反対側に移動させる。(塔を中心として全ての頂点を180度回転させる。) 塔は何回使っても良い。
移動が可能なら"possible"、不可能なら"impossible"を返す。
1≤N≤50
-1,000,000≤x,y≤1,000,000
[解法](終了後)
ある点から、頂点を2回使った後の移動先を考える。
上記の図で、黒い点が塔、青い点がある点の移動とする。
2回移動すると、黄色い線を使った三角形と、赤い線を使った三角形は相似形で2倍の大きになる(黄色と赤は平行線)。つまり、ある点について2回移動すると、3つの塔が作る三角形の線分の2倍移動できることになる。
そのため、2n回移動した後の点は以下のような塔3個三角形の2倍の三角形の組み合わせになる。(ちょっとずれてるけど。)
この三角形たちの頂点のいずれかであれば2n回後に移動できる。
頂点かどうかは、三角形のうち二片のベクトルが作る座標を、直行座標に変換して整数かどうかで確認する。これは、2片によるアフィン変換の逆行列から計算する。
2片が平行な場合(行列式が0の場合)、GCDの倍数かどうかで判定する。
頂点は複数あるので、目標点の全てについて、移動した場合に全ての頂点を相似形で移動できるか確認する。
これで2n回後に目標点に行けるかどうかが判定できる。
2n+1回後は、3つの塔のいずれかでの反転先が座標上にあるかで判定する。
[コード](C++)
[感想]
上は説明になっているのだろうか。。。
平行な場合を考えたり、longlongにしたり、などを含めて時間内に動くコードを書くのは難しかった。
SRM 645 Div1 Easy JanuszTheBusinessman
TopCoder Statistics - Problem Statement
[問題]
365日の中に、重なるかもしれないN個の区間がある。いくつかの区間を選び、すべての区間が選択した区間と重なるようにしたい。最小でいくつの区間を選べばよいか?
2≤N≤50
[解答](後で)
区間を終了日順でソートして未決定区間とする。
未決定区間の中の最初の区間と交わる区間の中で、(未決定区間以外を含む全ての区間から)終了日が一番遅いものを選択する。選択した区間と交わるものを未決定区間から省く。
これを未決定区間がなくなるまで繰り返す。
[コード](C++)
[感想]
本番は「(未決定区間以外を含む全ての区間から)終了日が一番遅いもの」の所を「(未決定区間の中での)終了日の一番遅いもの」としてしまい失敗。注意不足。。。
けど、失敗した人が多かったようで、レーティングはあまり下がらず。
SRM642 Div1 Medium TaroCutting
TopCoder Statistics - Problem Statement
[問題]
N本の木とD本のカッターがある。木は最初height[i]で1日にadd[i]のびていく。カッターは木の高さをdevice[i]丁度にすることができる。
各カッターは、1日に一回だけ使うことができる。
time日後、最小の木の高さの合計はどれぐらいか?
[解答](C++, 後で)
それぞれの木については、高々1回切ればいいので、木の高さの合計をコスト、流量(切った数と切らない木の合計)Nの最小費用流で計算する。
カッターはそれぞれの日に一度だけ使えるので、STARTからD * time個の頂点にコスト0、流量1の辺を張る。そこから、N本の木に対応する頂点まで更にコストdevice[i]+(time-i-1)*add[i]、流量1の辺をはる。カッターを使わない場合のため、STARTからN本の木までコストheight[i]+time*add[i]、流量1の辺も張る。木からSINKまでコスト0、流量1の辺を張る。
さらに、計算量を減らすため、カッターをdeviceでソートし、カッターiからカッターi+1にコスト(device[i]-device[i+1])(負の数だけど先の頂点はそれより大きい辺しかこないのでDijkstraでもOK)、流量Dの辺をはり、カッターから木の辺はそのカッターでしか切れない範囲までの辺にする。
[コード]
[感想]
テストケースによっては計算時間が1.9秒程度なので、ぎりぎり。。。
SRM642 Div1 Easy WaitingForBus
TopCoder Statistics - Problem Statement
[問題]
バス発着所にN台のバスがある。それぞれのバスは出発するとtime[i]後にバス発着所に帰ってくる。時刻0にいずれかのバスが確率prob[i]で出発し、戻ってくるといずれかの次のバスが同じく確率prob[i]で出発し、、、を繰り返す。
時刻sにバス発着所に着いた時、待ち時間の期待値はどれぐらいか?
1≤N≤100
1≤time[i]≤10^5
1≤prob[i]≤100
0≤s≤10^5
[解答]
dp[時刻]である時点でバスの出発時刻である確率を保持して時刻s以上の最初の時点(最大s+10^5)までDPで更新していく。sからs+10^5の間の Σ DP[i]x(i-s) で期待値を求める。計算量はO(s * N)
[コード](C++)
AtCoder Beginner Contest(ABC) #016 D - 一刀両断
かD: 一刀両断 - AtCoder Beginner Contest #016 | AtCoder
[問題]
多角形(凹凸)と線分1本が与えられる。線分により、多角形は何個に分割されるか?
[解答]
多角形の各辺について、線分との交差判定を行う。交差判定はベクトルの外積の符号判定を用いて行う(AB x AC * AB x AD < 0 && CD x CA * CD * CB <0)。交差の数の半分が分割数なので+1して返す。
[コード](Ruby)
https://paiza.io/projects/kpMphSQqdSNAW1VIGwnVLw
[感想]
線分の本数が増えると難しそう。。。
AtCoder Beginner Contest(ABC) #016 C - 友達の友達
- AtCoder Beginner Contest #016 | AtCoder
[問題]
N人について、友達関係M個が与えられる。
それぞれの人について、「友達の友達」の人数を返す。
[解答]
友達の友達から、友達と自分を引く。
[コード](Ruby)
https://paiza.io/projects/KIPFdk49anacJxZTYdkNIg
[感想]
ここはRubyが強い場面か。
AtCoder Beginner Contest(ABC) #016 B - A±B Problem
- AtCoder Beginner Contest #016 | AtCoder
[問題]
A,B,Cが与えられる。A+B=C、C-B=Dを満たすかどうかで、?(両方満たす), +(+のみ満たす), -(-のみ満たす), !(両方満たさない) のいづれかを返す。
[解答]
4通りチェックする。
[コード](Ruby)
https://paiza.io/projects/et4W53_HtgcPPBbEbsXO_Q
[感想]
論理和の理解テスト?