bzoj1296: [SCOI2009]粉刷匠

题目链接

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;
} 
posted @ 2018-05-20 17:56  zzzzx  阅读(114)  评论(0编辑  收藏  举报