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) << '
';
    }
}
原文地址:https://www.cnblogs.com/hznumqf/p/13863928.html