1296: [SCOI2009]粉刷匠

题目链接

题目大意:给定n*m的木板,每个点需要刷成1和0两种颜色之一,每次只能刷一行中连续的一段,一个点只能刷一次,求T次刷子最多能刷对多少个点

题解:dp
各行独立,互不影响,对每行处理数组f[i][j]表示这一行前i个刷j次能覆盖的最多格子数,这个可以O(m^3)求,具体就是枚举分割点k,使用前k个的信息更新[k+1,r]的信息,所以 0k<r 0 ≤ k < r ,这里是个为了方便的技巧,但是要注意……

f[m][i]0im1 然 后 需 要 从 每 行 的 f [ m ] [ i ] , 0 ≤ i ≤ m 中 选 择 1 个 计 入 答 案 , 就 是 分 组 背 包

O(nm3) 最 终 时 间 复 杂 度 为 O ( n m 3 )

我的收获:独立性,dp+dp

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int M=55;

int n,m,t,ans;
int sum[M],f[M][M],dp[M][2505];
char s[M];

void init()
{
    cin>>n>>m>>t;
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=m;j++) sum[j]=sum[j-1]+s[j]-'0';
        memset(f,0,sizeof(f));
        for(int j=1;j<=m;j++)
            for(int r=1;r<=m;r++)
                for(int k=0;k<r;k++){
                int tmp=sum[r]-sum[k];//[k,r]中1的个数 
                f[r][j]=max(f[r][j],f[k][j-1]+max(tmp,r-k-tmp));//1和0取max 
            }
        for(int j=1;j<=t;j++)
            for(int k=0;k<=min(m,j);k++)
                dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]);
    }
    for(int i=1;i<=t;i++) ans=max(ans,dp[n][i]);
    printf("%d\n",ans);
}

int main()
{
    init();
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值