BZOJ 1296--粉刷匠(DP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1296--粉刷匠(DP)相关的知识,希望对你有一定的参考价值。

1296: [SCOI2009]粉刷匠

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2324  Solved: 1340
[Submit][Status][Discuss]

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 。

 

 

题目链接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1296 

Solution

    分两次DP。。

    dp [ i ] [ j ] [ k ] [ 0 / 1 ] 表示第 i  行,到第 j 位,已经刷了 k 次,末尾是 0 / 1 的最多正确数。。。

    状态转移方程显然。。。。

    然后 f [ i ] 表示刷了 i 次最多正确数。。。再做一次DP。。。具体见代码。。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 60
using namespace std;
inline int Read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
char ch;
int n,m,k;
int mp[N][N],mp0[N][N],mp1[N][N],dp[N][N][N][2],f[2600];
int main(){
    n=Read();m=Read();k=Read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            mp0[i][j]=mp0[i][j-1];
            mp1[i][j]=mp1[i][j-1];
            ch=getchar();
            while(ch!=‘0‘&&ch!=‘1‘) ch=getchar();
            if(ch==‘0‘){
                 mp0[i][j]++;
                 mp[i][j]=0;
            }
            else {
                mp1[i][j]++;
                mp[i][j]=1;
            }
        }
    int cnt=min(m,k);
    for(int i=1;i<=n;i++)
        for(int t=1;t<=cnt;t++)
            for(int j=1;j<=m;j++){
                dp[i][j][t][0]=dp[i][j-1][t][0]+(mp[i][j]==0);
                dp[i][j][t][1]=dp[i][j-1][t][1]+(mp[i][j]==1);
                for(int l=0;l<j;l++){
                    dp[i][j][t][0]=max(dp[i][j][t][0],dp[i][l][t-1][1]+mp0[i][j]-mp0[i][l]);
                    dp[i][j][t][1]=max(dp[i][j][t][1],dp[i][l][t-1][0]+mp1[i][j]-mp1[i][l]);
                }
            }
    for(int i=1;i<=n;i++){
        for(int j=k;j>=0;j--){
            for(int l=1;l<=cnt;l++){
                if(j<l) break;
                f[j]=max(f[j],f[j-l]+max(dp[i][m][l][0],dp[i][m][l][1]));
            }
        }
    }
    printf("%d\n",f[k]);
    return 0;
}

  

  

This passage is made by Iscream-2001.

 

以上是关于BZOJ 1296--粉刷匠(DP)的主要内容,如果未能解决你的问题,请参考以下文章

[Bzoj 1296][Scoi2009] 粉刷匠 [DP + 分组背包]

bzoj1296SCOI2009粉刷匠

bzoj1296SCOI2009粉刷匠

BZOJ 1296: [SCOI2009]粉刷匠

粉刷匠(bzoj 1296)

1296: [SCOI2009]粉刷匠[多重dp]