Loading

Gym-101915K Poor Ramzi 区间DP

Gym-101915K Poor Ramzi 区间DP

题意

给出一段01序列,对这个序列进行划分,划分后的子区间合并其中1的和,问多少种划分方式使得划分后会成为回文序列

比如 \(0110\)有四种划分方式:

\[(0110) -> (2) \\(01)(10) -> (1)(1) \\(0)(11)(0) ->(0)(2)(0) \\(0)(1)(1)(0) \]

\[n \leq 50 \]

分析

想了半天用排列组合的办法没算出来

考虑到长度比较小,尝试用比较暴力的办法。

\(dp[l][r]\) 表示\([l,r]\)区间的划分方法

\[dp[l][r] = \sum dp[ll][rr],其中要求lsum == rsum \]

然后暴力枚举子区间即可

为方便实现,采用记忆化搜索

ll dp[55][55];
char s[55];


ll dfs(int l, int r) {
    if (l >= r) return 1;
    if (dp[l][r] != -1) return dp[l][r];
    int lsum = 0;
    ll res = 0;
    for (int i = l; i < r; i++) {
        lsum += s[i] == '1';
        int rsum = 0;
        for (int j = r; j > i; j--) {
            rsum += s[j] == '1';
            if (lsum == rsum) res += dfs(i + 1, j - 1) % MOD;
        }
    }
    res += dfs(r, r);
    res %= MOD;
    return dp[l][r] = res;
}

int main() {
    int T = readint();
    while (T--) {
        memset(dp, -1, sizeof dp);
        scanf("%s", s);
        int n = strlen(s);
        cout << dfs(0, n - 1) << '\n';
    }
}
posted @ 2020-10-23 14:20  MQFLLY  阅读(95)  评论(0编辑  收藏  举报