BZOJ 1296: [SCOI2009]粉刷匠 背包

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2174 Solved: 1253

Description

windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。

Input

输入文件paint.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,’0’表示红色,’1’表示蓝色。

Output

输出文件paint.out包含一个整数,最多能正确粉刷的格子数。

Sample Input

3 6 3

111111

000000

001100

Sample Output

16

HINT

30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。 100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。

Source


自己代码能力太差啦,写了五十分钟才把这道题写出来,真是弱鸡


dalao讲解


首先这道题我们先对于每一排进行一个dp,dp出在i这一排刷j次的最大收益,显然的一个三维dp
然后我们就dp前i个物品里刷j次,其中第i个物品刷k次的最大收益,用一维数组滚动优化空间,答案就是ans[T],也就是前n个物品一共刷T次

发现此类代码虽然简单,但是很可能一个小细节会挂得很惨,考试的时候也不敢不对拍,还得练练写暴力


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 60;
int N,M,T,a[MAXN][MAXN],dp[MAXN][MAXN],f[MAXN][MAXN],ans[3000],sum[MAXN]; 
//dp[i][j] 前i格,刷j次最多刷对几个 
int main()
{
    scanf( "%d%d%d", &N, &M, &T );
    for( register int i = 1; i <= N; i++ ) 
        for( register int j = 1; j <= M ; j++ ) scanf("%1d",&a[i][j]);
    for( register int r = 1; r <= N; r++ ) {
        sum[0] = 0;
        memset( dp, 0, sizeof(dp) );
        //dp[i][j] 为刷前i个刷j次最多收益 
        for( register int i = 1; i <= M; i++ ) sum[i] = sum[ i - 1 ] + a[r][i];
        for( register int i = 1; i <= M; i++ ) 
            for( register int j = 1; j <= i; j++ ) 
                for( register int k = 0; k < i; k++ ) 
                    dp[i][j] = max( dp[i][j], dp[k][ j - 1 ] + max( sum[i] - sum[k], i - k - sum[i] + sum[k] ) );
        for( register int i = 1; i <= M; i++ ) f[r][i] = dp[M][i];
    }
    for( register int i = 1; i <= N; i++ ) 
        for( register int j = T; j >= 1; j-- ) 
            for( register int k = 1; k <= M; k++ ) 
                if( k <= j ) ans[j] = max( ans[j], ans[ j - k ] + f[i][k] );

    printf("%d\n",ans[T]);

    return 0;
}

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值