CODE FESTIVAL 2016 qual C : D - Friction

code-festival-2016-qualc.contest.atcoder.jp

当初の方針

  • Cが解けなくてこちらに来る
  • 部分点解法を狙おう
  • うーん、O(H^4)にしかならない・・・
  • cost[i][y1][y2]はcost[i][y1-1][y2-1]の一番下しか違いがないことに気づく
  • 再利用すればO(H^3)になるぞ
  • でも実装がとても重くてバグりそう・・・
  • 撤退してCを通すか・・・通せたらこちらを実装しよう

そのままCを通せず、終了

解法を見て

頭いい。このように考察すれば簡単な問題に落とし込めるのはおもしろい。

トポロジカル順序はfor文できれいに書けそうにないので、メモ化再帰で解く。

実装 → 案の上バグらせる

括弧が足りなくて、おかしな挙動をしていた

    int[][][] cost = new int[w - 1][h + 1][h + 1];
    for (int i = 0; i < w - 1; ++i) {
      // left
      for (int j = 0; j < h; ++j) {
        for (int k = 0; k <= h - 1 - j; ++k) {
          cost[i][j][0] += field[k][i] == field[j + k][i + 1] ? 1 : 0;
        }
        for (int k = 1; k <= h - 1 - j; ++k) {
          cost[i][j + k][k] = cost[i][j + k - 1][k - 1]
              - (field[h - 1 - j - (k - 1)][i] == field[h - 1 - (k - 1)][i + 1] ? 1 : 0);
        }
      }
      // right: j = 0のケースはもう計算済みなので注意
      for (int j = 1; j < h; ++j) {
        for (int k = 0; k <= h - 1 - j; ++k) {
          cost[i][0][j] += field[j + k][i] == field[k][i + 1] ? 1 : 0;
        }
        for (int k = 1; k <= h - 1 - j; ++k) {
          cost[i][k][j + k] = cost[i][k - 1][j + k - 1]
              - (field[h - 1 - (k - 1)][i] == field[h - 1 - j - (k - 1)][i + 1] ? 1 : 0);
        }
      }
    }

これを、

cost[i][j + k][k] = cost[i][j + k - 1][k - 1] - field[h - 1 - j - (k - 1)][i] == field[h - 1 - (k - 1)][i + 1] ? 1 : 0;

と書いてしまうと、

cost[i][j + k][k] = (cost[i][j + k - 1][k - 1] - field[h - 1 - j - (k - 1)][i]) == field[h - 1 - (k - 1)][i + 1] ? 1 : 0;

となってしまい、基本0が代入されていくことになる。

これに見つけるのに時間を費やしたので、気を付けたい。

直したらACできた。
サンプルで見つけられてよかった部類。

Submission #949816 - CODE FESTIVAL 2016 qual C | AtCoder