BZOJ1296:[SCOI2009]粉刷匠

1296: [SCOI2009]粉刷匠

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2038  Solved: 1182
[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 。

嗯哼

思路{

  考虑对每个串进行一下序列划分型DP,求出每个串刷i次的最优结果。

  那我就相当于对这n个串做分组背包了。时间复杂度O(n^4).

}

#include<bits/stdc++.h>
#define RG register
#define il inline
#define N 2510
#define M 60
#define LL long long
using namespace std;
int dp[M][N],sum1[M],sum2[M],n,m,T;
char s[M];int DP[M][N];
int main(){
  freopen("paint.in","r",stdin);
  freopen("paint.out","w",stdout);
  scanf("%d%d%d",&n,&m,&T);
  for(int k=1;k<=n;++k){//N
    scanf("%s",s+1);memset(dp,0,sizeof(dp));
    for(int i=1;i<=m;++i)sum1[i]=sum1[i-1]+(s[i]=='1'),sum2[i]=sum2[i-1]+(s[i]=='0');
    memset(dp,0,sizeof(dp));dp[1][1]=1;
    for(int i=2;i<=m;++i){
      for(int j=1;j<=m;++j)
	for(int i1=0;i1<i;++i1){
	  dp[i][j]=max(dp[i1][j-1]+max(sum2[i]-sum2[i1],sum1[i]-sum1[i1]),dp[i][j]);
	}
    }
    for(int i=1;i<=T;++i){
      int tmp=min(i,m);
      for(int j=0;j<=tmp;++j)
	DP[k][i]=max(DP[k][i],DP[k-1][i-j]+dp[m][j]);
    }
  }int Ans=0;
  for(int i=1;i<=T;++i)Ans=max(Ans,DP[n][i]);cout<<Ans;
  return 0;
}

 

posted @ 2017-08-14 23:34  QYP_2002  阅读(169)  评论(0编辑  收藏  举报