mini notes

競技プログラミングの解法メモを残していきます。

ARC032 C - 仕事計画

問題:C - 仕事計画

解答:Submission #15233951 - AtCoder Regular Contest 032

解法:区間スケジュールで最も多くの仕事をこなすには、終了時間の速い順に仕事をソートし、貪欲に仕事を選んでゆけばよい。
ただしこの問題では、仕事の数が同数の場合は選んだ仕事の番号を開始時刻の順に並べた列が辞書順最小となるようにしなければならないため、工夫が必要となる。

次のようなdpを考える。
dp[i].id : 時間iで次に選ぶべき仕事の番号、dp[i].cnt:時間iでそれ以降に出来る仕事の個数
このdpは後ろから遷移させることが出来る。

①時間iでその時間から始まる仕事を選ばないとき
dp[i] = dp[i+1]

②時間iでその時間から始まる仕事を選ぶとき
選ぶ対象の仕事の番号をxとし、仕事xの開始時間をst[x]、終了時間をen[x]とする。
dp[i].cnt < dp[en[x]].cnt + 1の場合、個数が更新されるため、仕事xを選んだほうが良い。
dp[i].cnt == dp[en[x]].cnt + 1の場合、dp[i].id > x の場合は仕事の個数が同数でもソート順で有利になるため、仕事xを選んだほうが良い。

選んだ仕事の復元は現在時刻tを保持し、「dp[t].idで次にやる仕事のidを取得し、その仕事の終了時刻をtに代入する」ことを繰り返せばよい。