动态规划 BZOJ1296 [SCOI2009]粉刷匠

1296: [SCOI2009]粉刷匠

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

Source

先每个木板分开暴力地计算刷t/m次最多能刷对的数量,再进行汇总地动归

正解很容易想到

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,m,t,ans;
 7 char s[60];
 8 int sum[60],f[60][60],g[60][2510];
 9 int main(){
10     scanf("%d%d%d",&n,&m,&t);
11     for(int i=1;i<=n;i++){
12         scanf("%s",s+1);
13         for(int j=1;j<=m;j++) sum[j]=sum[j-1]+(s[j]=='1');
14         for(int k=1;k<=m;k++)
15             for(int j=1;j<=m;j++){
16                 f[j][k]=0;
17                 for(int p=0;p<=j-1;p++) f[j][k]=max(f[j][k],f[p][k-1]+max(sum[j]-sum[p],j-p-sum[j]+sum[p]));
18             }
19         for(int j=1;j<=t;j++)
20             for(int k=1;k<=min(j,m);k++) g[i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]);
21     }
22     for(int i=1;i<=t;i++) ans=max(ans,g[n][i]);
23     printf("%d
",ans);
24     return 0;
25 }
原文地址:https://www.cnblogs.com/zwube/p/7077627.html