BZOJ1296:[SCOI2009]粉刷匠
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; }