AtCoder Regular Contest 036 C: 偶然ジェネレータ
解法
dp[pos][diff0][diff1]:= pos文字目まで見た時に、(0の文字数)-(1の文字数)の最大値がdiff0であり、(1の文字数)-(0の文字数)の最大値がdiff1である組み合わせの数
とする。
S[pos]='0' のとき [pos][diff0][diff1] から [pos][diff0+1][diff1-1] に遷移し、 S[pos]='1' のとき [pos][diff0][diff1] から [pos][diff0-1][diff1+1] に遷移する。
S[pos]='?' のときは両方に遷移する。
コード
import java.util.Scanner; class Main { private static final int MOD = 1000000007; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int K = sc.nextInt(); char[] S = sc.next().toCharArray(); sc.close(); /* * dp[pos][diff0][diff1]:= pos文字目まで見た時に、 (0の文字数)-(1の文字数)の最大値がdiff0であり、 * (1の文字数)-(0の文字数)の最大値がdiff1である組み合わせの数 */ int[][][] dp = new int[N + 1][K + 2][K + 2]; dp[0][0][0] = 1; for (int pos = 0; pos < N; pos++) { for (int diff0 = 0; diff0 <= K; diff0++) { for (int diff1 = 0; diff1 <= K; diff1++) { if (dp[pos][diff0][diff1] == 0) { continue; } if (S[pos] == '0' || S[pos] == '?') { if (diff1 > 0) { dp[pos + 1][diff0 + 1][diff1 - 1] += dp[pos][diff0][diff1]; dp[pos + 1][diff0 + 1][diff1 - 1] %= MOD; } else { dp[pos + 1][diff0 + 1][0] += dp[pos][diff0][0]; dp[pos + 1][diff0 + 1][0] %= MOD; } } if (S[pos] == '1' || S[pos] == '?') { if (diff0 > 0) { dp[pos + 1][diff0 - 1][diff1 + 1] += dp[pos][diff0][diff1]; dp[pos + 1][diff0 - 1][diff1 + 1] %= MOD; } else { dp[pos + 1][0][diff1 + 1] += dp[pos][0][diff1]; dp[pos + 1][0][diff1 + 1] %= MOD; } } } } } int ans = 0; for (int i = 0; i <= K; i++) { for (int j = 0; j <= K; j++) { ans += dp[N][i][j]; ans %= MOD; } } ans %= MOD; System.out.println(ans); } }
感想
「最大値」を引数にもつのがポイントな気がする。次出てきた時解けるのか……?