目前(2019-6-12)Luogu上第一篇题解是错误的,但是能(A) link
(hack)数据来自洛谷讨论
它的(DP)方式是设f[i][j][k][0/1]
表示涂了(k)次,当前涂到了((i,j))这个点,这个点有没有涂对((0/1))
第一篇题解基本上是正确的(在我看来),但其中的一个小错误是,它强制当前行只能由上一行转移过来,而忽略了某些行其实可以不涂的条件
所以在转移当前行时应该将它之前的行都枚举一遍,选最优的转移
这样的时间复杂度会变高,理论上应该会TLE,但实际上跑的还是挺快的(数据太水)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
char read_c() {
char c = getchar();
while(c != '1' && c != '0') c = getchar();
return c - 48;
}
bool mat[55][55];
int f[55][55][2510][2];
int main() {
int n = read(), m = read(), t = read();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
mat[i][j] = read_c();
int ans = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
for(int k = 1; k <= t; ++k) {
if(j == 1) {
for(int o = 1; o <= i; ++o)
f[i][j][k][0] = max(f[i][j][k][0], max(f[i-o][m][k-1][0], f[i-o][m][k-1][1])),
f[i][j][k][1] = max(f[i][j][k][1], max(f[i-o][m][k-1][1], f[i-o][m][k-1][0]) + 1);
}
else if(mat[i][j] == mat[i][j-1])
f[i][j][k][1] = max(f[i][j-1][k][1], f[i][j-1][k-1][0]) + 1,
f[i][j][k][0] = max(f[i][j-1][k][0], f[i][j-1][k-1][1]);
else
f[i][j][k][1] = max(f[i][j-1][k][0], f[i][j-1][k-1][1]) + 1,
f[i][j][k][0] = max(f[i][j-1][k-1][0], f[i][j-1][k][1]);
ans = max(ans, max(f[i][j][k][0], f[i][j][k][1]));
}
cout << ans;
return 0;
}