1296: [SCOI2009]粉刷匠
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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;
}