2021年7月26日月曜日

KUPC 2016 H - 壁壁壁壁壁壁壁

KUPC 2016 H - 壁壁壁壁壁壁壁

位置iiからi+1i+1に補強材を移動する量をxix_iとして制約を書き下す。n=4n=4なら

  • A1x1B1A_1-x_1 \ge B_1
  • A2+x1x2B2A_2 + x_1-x_2 \ge B_2
  • A3+x2x3B3A_3 + x_2-x_3 \ge B_3
  • A4+x3B4A_4+x_3 \ge B_4

という制約の下でx1+x2+x3+x4|x_1|+|x_2|+|x_3|+|x_4|を最小化する問題になっている。

fi(x)f_i(x)x1,...,xi1,xi=xx_1, ..., x_{i-1}, x_i=xまでを決定した際の最小コストとする。slope trick向けに制約を変形すると、

  • x1A1B1x_1 \le A_1-B_1
  • x1x2(A2B2)x_1 \ge x_2-(A_2-B_2)
  • x2x3(A3B3)x_2 \ge x_3-(A_3-B_3)
  • x3B4A4x_3 \ge B_4-A_4

となって、一番上のx1x_1に関する制約を無視するとfif_iの漸化式が得られる:

  • f1(x)=xf_1(x) = |x|
  • f2(x)=mintx(A2B2)f1(t)+xf_2(x) = \min_{t \ge x - (A_2-B_2)}f_1(t) + |x|
  • f3(x)=mintx(A3B3)f2(t)+xf_3(x) = \min_{t \ge x - (A_3-B_3)}f_2(t) + |x|

登場する操作はすべてslope trickで表現できて、答えは凸性により、B4A4B_4-A_4arg minxf3(x)\argmin_xf_3(x)の大きいほうの位置でf3f_3の値を求めると得られる。

制約x1A1B1x_1 \le A_1-B_1については、この範囲を超えると高いコストがかかることにして対処したい。x1x_1A1B1A_1-B_111超過することによる利益が高々CCであるとき、f1(x)=x+Cmax(0,x(A1B1))f_1(x) = |x| + C\max(0, x-(A_1-B_1))とすればよい。CCの具体的な値としては、制約を11だけ破っている状態を解消するために1つの補強材を端から端へ移動するとN1N-1のコストがかかるので、N1N-1でよい。

2021年7月24日土曜日

CodeChef - CCDSAP Exam

CodeChef - CCDSAP Exam

slope trickの練習問題として解いた。

iiの初期位置をaia_iとし、人iiを位置xxに配置した場合の人1,2,...,i1, 2, ..., iに関するコストの総和の最小値をfi(x)f_i(x)とする。

左右の境界を無視するとfi(x)=mintx2fi1(t)+xai=mintxfi1(t2)+xaif_{i}(x) = \min_{t \le x-2}f_{i-1}(t) + |x-a_{i}| = \min_{t \le x}f_{i-1}(t-2)+|x-a_i|と表せる。これだけなら普通のslope trickで解けるが実際には境界を越えられないところが難しい。

境界を越えたら大きなコストがかかるように、xai|x-a_i|の代わりに定数CCを定めてCmax(0,1x)+xai+Cmax(0,xN)C\max(0, 1-x) + |x-a_i| + C\max(0, x-N)を追加することを考えたが、これは優先度付きキューに一つずつ挿入していく方法では難しそう。平衡二分木で多重集合を管理すればいけそう? → 平衡二分木slope trickを作ろうとしたが、最小値の更新が自明にはできない。おそらく任意のxxについてf(x)f(x)の値が取得できる必要があって、実現方法がわからなかった。ただ、min\minがわからなくてもarg min\argminは容易に取得・更新できる。これだけわかれば最適解を貪欲に復元できそう。最適解における人iiの位置をyiy_iとする。yN=arg minxfN(x)y_N=\argmin_x f_{N}(x)は既知であり、yi+1y_{i+1}が既知であるときyiy_i

yi=min(arg minxfi(x),yi+12)y_i = \min(\argmin_x f_{i}(x), y_{i+1}-2)

と決定できる。arg min\argminが複数ある時はどれを取ってもよい。