bzoj 1296 【粉刷匠】

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

思路:
dp题目啊。
怎么想到的?恩。。。。感觉这个状态可以从上一个转移。
两边dp:
第一遍dp横向的
f[i][j]表示前i个格子染色t次正确的最大值。
f[i][j]=max(f[i][j],f[k][j-1]+max(sum[i]-sum[k],k-p-(sum[i]-sum[k]));
再dp纵向的。
dp[i][j]表示前i行染j次
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]

有个要注意的循环。。键代码

/**************************************************************
    Problem: 1296
    User: mars_ch
    Language: C++
    Result: Accepted
    Time:2180 ms
    Memory:1820 kb
****************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//by mars_ch
int n,m,t;
int f[51][2505],dp[51][2505];
char s[55],sum[55];
int main()
{
    scanf("%d%d%d",&n,&m,&t); 
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s);
        for(int j=0;j<m;j++)
        {
            sum[j+1]=sum[j]+(s[j] -'0');
        }
        memset(f,0,sizeof(f));
        f[1][1]=1;
        for(int j=1;j<=m;j++)
        {
            for(int k=1;k<=t;k++)
            {
                for(int p=0;p<=j;p++)   //要从0开始,不是1
                {
                    f[j][k]=max(f[j][k],f[p][k-1]+max(sum[j]-sum[p],j-p-sum[j]+sum[p]));
                }
            }
        }
        /*for(int j=1;j<=m;j++)
        {
            for(int k=1;k<=t;k++)
            {
                printf("%d ",f[j][k]);
            }
            puts("");
        }*/

        for(int j=1;j<=t;j++)
        {
            for(int k=1;k<=j;k++)
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]);
            }
        }
    }
    printf("%d\n",dp[n][t]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值