bzoj1296: [SCOI2009]粉刷匠
题目链接
题解
对于每一行的每种消耗dp
抽离装态,进行整体容量的背包dp
刚开始写的把每种状态全抽了一起背包...然后对于每行选取了好多状态...然后GG惹...
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar(); }
while(c <= '9' &&c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
const int maxn = 67 ;
int n,m,t;
int sumr[maxn][maxn],dp[maxn][maxn];
int f[maxn][maxn * maxn],tmp[maxn];
int sumb[maxn][maxn];
int main() {
n = read(); m = read();t = read();
char p[maxn][maxn];
for(int i = 1;i <= n;++ i)
scanf("%s",p[i] + 1);
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= m;++ j) {
if(p[i][j] == '0')
sumr[i][j] = sumr[i][j - 1] + 1;
else sumr[i][j] = sumr[i][j - 1];
if(p[i][j] == '1')
sumb[i][j] = sumb[i][j - 1] + 1;
else sumb[i][j] = sumb[i][j - 1];
}
int num = 0 ;
for(int T = 1;T <= n;++ T) {
memset(dp,0,sizeof dp);
memset(tmp,0,sizeof tmp);
//for(int i = 1;i <= m;++ i) dp[i][1] = std::max(sumr[T][i],sumb[T][i]);
for(int i = 1;i <= m;++ i)
for(int j = 1;j <= m;++ j) {
for(int k = 0;k < i;++ k) {
int ttt = std::max(sumr[T][i] - sumr[T][k],sumb[T][i] - sumb[T][k]);
dp[i][j] = std::max(dp[i][j],dp[k][j - 1] + ttt);
}
}
for(int i = 1;i <= m;++ i)
for(int k = i;k <= t;++ k) {
f[T][k] = std::max(f[T][k],f[T - 1][k - i] + dp[m][i]);
}
}
printf("%d\n",f[n][t]);
return 0;
}