Submission #949816


Source Code Expand

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
import java.util.function.BiFunction;
import java.util.function.Function;

public class Main {
  void run() {
    int h = ni();
    int w = ni();
    int[][] field = new int[h][w];
    for (int i = 0; i < h; ++i) {
      String str = sc.next();
      for (int j = 0; j < w; ++j) {
        field[i][j] = str.charAt(j);
      }
    }

    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);
        }
      }
    }

    int[][][] dp = new int[w - 1][h + 1][h + 1];
    for (int i = 0; i < w - 1; ++i) {
      for (int j = 0; j < h + 1; ++j) {
        Arrays.fill(dp[i][j], 1 << 28);
      }
    }
    for (int i = 0; i < w - 1; ++i) {
      dp[i][0][0] = 0;
    }
    for (int i = 0; i < w - 1; ++i) {
      for (int j = 0; j <= h; ++j) {
        for (int k = 0; k <= h; ++k) {
          dfs(dp, cost, i, j, k);
        }
      }
    }
    int sum = 0;
    for (int i = 0; i < w - 1; ++i) {
      sum += dp[i][h][h];
    }
    System.out.println(sum);
  }

  int dfs(int[][][] dp, int[][][] cost, int i, int j, int k) {
    if (dp[i][j][k] != 1 << 28) {
      return dp[i][j][k];
    }
    int min = 1 << 28;
    if (j > 0) {
      min = Math.min(min, dfs(dp, cost, i, j - 1, k) + cost[i][j - 1][k]);
    }
    if (k > 0) {
      min = Math.min(min, dfs(dp, cost, i, j, k - 1) + cost[i][j][k - 1]);
    }
    return dp[i][j][k] = min;
  }

  Scanner sc = new Scanner(System.in);

  public static void main(String[] args) {
    new Main().run();
  }

  int ni() {
    return Integer.parseInt(sc.next());
  }

  void debug(Object... os) {
    System.err.println(Arrays.deepToString(os));
  }

  class BIT<T> {
    int n;
    ArrayList<T> bit;
    BiFunction<T, T, T> bif;

    BIT(int n, BiFunction<T, T, T> bif, T defaultValue) {
      this.n = n;
      bit = new ArrayList<>(n + 1);
      for (int i = 0; i < n + 1; ++i) {
        bit.add(defaultValue);
      }
      this.bif = bif;
    }

    void update(int i, T v) {
      for (int x = i; x <= n; x += x & -x) {
        bit.set(x, bif.apply(bit.get(x), v));
      }
    }

    T reduce(int i, T defaultValue) {
      T ret = defaultValue;
      for (int x = i; x > 0; x -= x & -x) {
        ret = bif.apply(ret, bit.get(x));
      }
      return ret;
    }
  }

  long MOD = 1_000_000_007;

  long pow(long a, long r) {
    long sum = 1;
    while (r > 0) {
      if ((r & 1) == 1) {
        sum *= a;
        sum %= MOD;
      }
      a *= a;
      a %= MOD;
      r >>= 1;
    }
    return sum;
  }

  long C(int n, int r) {
    long sum = 1;
    for (int i = n; 0 < i; --i) {
      sum *= i;
      sum %= MOD;
    }
    long s = 1;
    for (int i = r; 0 < i; --i) {
      s *= i;
      s %= MOD;
    }
    sum *= pow(s, MOD - 2);
    sum %= MOD;

    long t = 1;
    for (int i = n - r; 0 < i; --i) {
      t *= i;
      t %= MOD;
    }
    sum *= pow(t, MOD - 2);
    sum %= MOD;

    return sum;
  }

  double GOLDEN_RATIO = (1.0 + Math.sqrt(5)) / 2.0;

  /**
   * 黄金分割探索
   *
   * @param left  下限
   * @param right 上限
   * @param f     探索する関数
   * @param comp  上に凸な関数を探索するときは、Comparator.comparingDouble(Double::doubleValue)
   *              下に凸な関数を探索するときは、Comparator.comparingDouble(Double::doubleValue).reversed()
   * @return 極値の座標x
   */
  double goldenSectionSearch(double left, double right, Function<Double, Double> f, Comparator<Double> comp) {
    double c1 = divideInternally(left, right, 1, GOLDEN_RATIO);
    double c2 = divideInternally(left, right, GOLDEN_RATIO, 1);
    double d1 = f.apply(c1);
    double d2 = f.apply(c2);
    while (right - left > 1e-9) {
      if (comp.compare(d1, d2) > 0) {
        right = c2;
        c2 = c1;
        d2 = d1;
        c1 = divideInternally(left, right, 1, GOLDEN_RATIO);
        d1 = f.apply(c1);
      } else {
        left = c1;
        c1 = c2;
        d1 = d2;
        c2 = divideInternally(left, right, GOLDEN_RATIO, 1);
        d2 = f.apply(c2);
      }
    }
    return right;
  }

  /**
   * [a,b]をm:nに内分する点を返す
   */
  double divideInternally(double a, double b, double m, double n) {
    return (n * a + m * b) / (m + n);
  }
}

Submission Info

Submission Time
Task D - Friction
User arukuka
Language Java8 (OpenJDK 1.8.0)
Score 800
Code Size 5335 Byte
Status AC
Exec Time 1467 ms
Memory 293884 KB

Judge Result

Set Name Sample Subtask All
Score / Max Score 0 / 0 300 / 300 500 / 500
Status
AC × 5
AC × 20
AC × 41
Set Name Test Cases
Sample 0_000.txt, 0_001.txt, 0_002.txt, 0_003.txt, 0_004.txt
Subtask 0_000.txt, 0_001.txt, 1_005.txt, 1_006.txt, 1_007.txt, 1_008.txt, 1_009.txt, 1_010.txt, 1_011.txt, 1_012.txt, 1_013.txt, 1_014.txt, 1_015.txt, 1_016.txt, 1_017.txt, 1_018.txt, 1_019.txt, 1_020.txt, 1_021.txt, 1_022.txt
All 0_000.txt, 0_001.txt, 0_002.txt, 0_003.txt, 0_004.txt, 1_005.txt, 1_006.txt, 1_007.txt, 1_008.txt, 1_009.txt, 1_010.txt, 1_011.txt, 1_012.txt, 1_013.txt, 1_014.txt, 1_015.txt, 1_016.txt, 1_017.txt, 1_018.txt, 1_019.txt, 1_020.txt, 1_021.txt, 1_022.txt, 2_023.txt, 2_024.txt, 2_025.txt, 2_026.txt, 2_027.txt, 2_028.txt, 2_029.txt, 2_030.txt, 2_031.txt, 2_032.txt, 2_033.txt, 2_034.txt, 2_035.txt, 2_036.txt, 2_037.txt, 2_038.txt, 2_039.txt, 2_040.txt
Case Name Status Exec Time Memory
0_000.txt AC 125 ms 9556 KB
0_001.txt AC 135 ms 9556 KB
0_002.txt AC 125 ms 9556 KB
0_003.txt AC 124 ms 9552 KB
0_004.txt AC 125 ms 9684 KB
1_005.txt AC 124 ms 9556 KB
1_006.txt AC 178 ms 13416 KB
1_007.txt AC 174 ms 12912 KB
1_008.txt AC 177 ms 12968 KB
1_009.txt AC 178 ms 13440 KB
1_010.txt AC 178 ms 13440 KB
1_011.txt AC 172 ms 13088 KB
1_012.txt AC 174 ms 13424 KB
1_013.txt AC 168 ms 10960 KB
1_014.txt AC 167 ms 13300 KB
1_015.txt AC 165 ms 11496 KB
1_016.txt AC 173 ms 12924 KB
1_017.txt AC 140 ms 9940 KB
1_018.txt AC 170 ms 12968 KB
1_019.txt AC 163 ms 10936 KB
1_020.txt AC 178 ms 13108 KB
1_021.txt AC 173 ms 12928 KB
1_022.txt AC 180 ms 13332 KB
2_023.txt AC 137 ms 9552 KB
2_024.txt AC 1449 ms 292408 KB
2_025.txt AC 1394 ms 290848 KB
2_026.txt AC 1389 ms 293200 KB
2_027.txt AC 1399 ms 292776 KB
2_028.txt AC 1425 ms 290520 KB
2_029.txt AC 242 ms 20364 KB
2_030.txt AC 1402 ms 293884 KB
2_031.txt AC 256 ms 19336 KB
2_032.txt AC 1416 ms 290964 KB
2_033.txt AC 499 ms 65500 KB
2_034.txt AC 1403 ms 291520 KB
2_035.txt AC 897 ms 147308 KB
2_036.txt AC 1428 ms 290136 KB
2_037.txt AC 230 ms 17896 KB
2_038.txt AC 1467 ms 292432 KB
2_039.txt AC 202 ms 15936 KB
2_040.txt AC 1412 ms 291076 KB