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