1. 程式人生 > >1296: [SCOI2009]粉刷匠

1296: [SCOI2009]粉刷匠

%s 一個 enter esp 選擇 set ref ros spa

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

註意,每個格子只能塗一次

先暴力統計f[k][j],前k個格子塗j次,最多能塗幾個

然後背包動規

 1 #include<iostream>
 2
#include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 char ch[60]; 7 int n,m,t,ans; 8 int sum[60],f[60][60],g[60][2600]; 9 10 int main() 11 { 12 scanf("%d%d%d",&n,&m,&t); 13 for(int i=1;i<=n;i++) 14 { 15 memset(sum,0,sizeof(sum));
16 memset(f,0,sizeof(f)); 17 scanf("%s",ch+1); 18 for(int j=1;j<=m;j++) 19 sum[j]=sum[j-1]+(ch[j]==1); 20 for(int j=1;j<=m;j++) 21 for(int k=1;k<=m;k++) 22 { 23 for(int l=0;l<k;l++) 24 f[k][j]=max(f[k][j],f[l][j-1]+max(sum[k]-sum[l],(k-l)-(sum[k]-sum[l]))); 25 } 26 for(int j=1;j<=t;j++) 27 for(int k=1;k<=min(j,m);k++) 28 g[i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]); 29 } 30 for(int i=1;i<=t;i++) 31 ans=max(ans,g[n][i]); 32 printf("%d\n",ans); 33 return 0; 34 }

1296: [SCOI2009]粉刷匠