bzoj 1296: [SCOI2009]粉刷匠
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 。
Source
http://www.lydsy.com/JudgeOnline/problem.php?id=1296
线性dp
1 #include <stdio.h> 2 #define MAXN 3000 3 int f[MAXN][MAXN],sum[MAXN]; 4 int dp[MAXN][MAXN]; 5 char in[MAXN]; 6 int max(int a,int b) 7 { 8 if(a>b) return a; 9 return b; 10 } 11 int min(int a,int b) 12 { 13 if(a<b) return a; 14 return b; 15 } 16 int main() 17 { 18 int k,i,j,n,m,t,l,ans=-1; 19 scanf("%d%d%d",&n,&m,&t); 20 for(k=1;k<=n;k++) 21 { 22 scanf("%s",in+1); 23 for(i=1;i<=m;i++) 24 sum[i]=sum[i-1]+(in[i]=='1'); 25 for(i=1;i<=m;i++) 26 for(j=1;j<=m;j++) 27 { 28 f[j][i]=0; 29 for(l=0;l<j;l++) 30 { 31 int cnt=sum[j]-sum[l]; 32 f[j][i]=max(f[j][i],f[l][i-1]+max(cnt,j-l-cnt)); 33 } 34 } 35 for(i=1;i<=t;i++) 36 { 37 int cnt=min(m,i); 38 for(j=1;j<=cnt;j++) 39 dp[k][i]=max(dp[k][i],dp[k-1][i-j]+f[m][j]); 40 } 41 } 42 for(i=1;i<=t;i++) 43 ans=max(ans,dp[n][i]); 44 printf("%d\n",ans); 45 return 0; 46 }