题意
个长为
的 01 序列,可以涂色
次。一次涂色涂一个序列的某一段(连续),获得的分数为这一段中 0 或者 1 的个数。一个位置不能重复涂。求最大分数。
题解
对每一序列暴力 DP 即可,可以算出每一序列涂 次的答案。于是可以转化为一个背包问题。时间复杂度为
。
#include <bits/stdc++.h> #define INF 2000000000 using namespace std; typedef long long ll; int read(){ int f = 1, x = 0; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();} while(c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar(); return f * x; } int n, m, t; char s[55][55]; int lis[55], f[55][55]; int g[2505] = {0}, tmp[2505]; void init(){ n = read(), m = read(), t = read(); for (int i = 0; i < n; ++i) scanf("%s", s[i]); } void solve(){ lis[0] = 0; for (int i = 0; i < n; ++i){ int tot = 0; for (int j = 0; j < m; ){ int k = j; while (k < m && s[i][j] == s[i][k]) ++k; lis[++tot] = k - j; j = k; } memset(f, 0, sizeof(f)); for (int j = 1; j <= tot; ++j){ int sm = 0; for (int k = j; k >= 1; --k){ if ((j - k) % 2 == 0) sm += lis[k]; for (int l = k; l >= 1; --l) f[j][l] = max(f[j][l], f[k - 1][l - 1] + sm); } } for (int j = 0; j <= t; ++j) tmp[j] = g[j]; for (int w = 1; w <= tot; ++w){ int maxi = 0; for (int j = w; j <= tot; ++j) maxi = max(maxi, f[j][w]); for (int j = w; j <= t; ++j) g[j] = max(g[j], tmp[j - w] + maxi); } } printf("%d\n", g[t]); } int main(){ init(); solve(); return 0; }