バイトの競プロメモ

主に競技プログラミング

B - 天下一魔力発電 天下一プログラマーコンテスト2016予選B

問題概略
括弧の対応を取る時の最小操作回数
移動回数+変更回数

制約<=100

解法
dpは状態の纏め上げだということを忘れていた。
愚直に考えると、2^100になってしまうが、現在見終わった場所、最後に変更した場所、(が開いている数が同じなら一つの状態に纏められる。
括弧が(か),変更する場合としない場合の4通りがある。操作回数を入れると処理が面倒なので、変更回数を入れることとする。

public static void solve() {
        //longを忘れるなオーバーフローするぞ
        char[] s = next().toCharArray();
        N = s.length;
        //ここまで見た。 最後の変更 開いた括弧の数。
        int[][][] dp = new int[N + 1][101][101];
        fill(dp, INF);
        dp[0][0][0] = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < i + 1; j++) {
                for (int k = 0; k < 101; k++) {
                    if (dp[i][j][k] == INF) continue;
                    //kは自分より左での個数
                    int now = dp[i][j][k];
                    if (s[i] == '(') {
                        dp[i + 1][j][k + 1] = Math.min(dp[i + 1][j][k + 1], now);
                        if (k > 0) dp[i + 1][i][k - 1] = Math.min(dp[i + 1][i][k - 1], now + 1);
                    } else {
                        //基本的に(にする
                        dp[i + 1][i][k + 1] = Math.min(dp[i + 1][i][k + 1], now + 1);
                        if (k > 0) dp[i + 1][j][k - 1] = Math.min(dp[i + 1][j][k - 1], now);
                    }
                }
            }
        }
        //i = N
        for (int j = 0; j < 101; j++) {
            chMin(dp[N][j][0] + j);
        }
        System.out.println(minRes);
    }