题目大意:给定n*m的木板,每个点需要刷成1和0两种颜色之一,每次只能刷一行中连续的一段,一个点只能刷一次,求T次刷子最多能刷对多少个点
题解:dp
各行独立,互不影响,对每行处理数组f[i][j]表示这一行前i个刷j次能覆盖的最多格子数,这个可以O(m^3)求,具体就是枚举分割点k,使用前k个的信息更新[k+1,r]的信息,所以
0≤k<r
0
≤
k
<
r
,这里是个为了方便的技巧,但是要注意……
然后需要从每行的f[m][i],0≤i≤m中选择1个计入答案,就是分组背包 然 后 需 要 从 每 行 的 f [ m ] [ i ] , 0 ≤ i ≤ m 中 选 择 1 个 计 入 答 案 , 就 是 分 组 背 包
最终时间复杂度为O(nm3) 最 终 时 间 复 杂 度 为 O ( n m 3 )
我的收获:独立性,dp+dp
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int M=55;
int n,m,t,ans;
int sum[M],f[M][M],dp[M][2505];
char s[M];
void init()
{
cin>>n>>m>>t;
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++) sum[j]=sum[j-1]+s[j]-'0';
memset(f,0,sizeof(f));
for(int j=1;j<=m;j++)
for(int r=1;r<=m;r++)
for(int k=0;k<r;k++){
int tmp=sum[r]-sum[k];//[k,r]中1的个数
f[r][j]=max(f[r][j],f[k][j-1]+max(tmp,r-k-tmp));//1和0取max
}
for(int j=1;j<=t;j++)
for(int k=0;k<=min(m,j);k++)
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]);
}
for(int i=1;i<=t;i++) ans=max(ans,dp[n][i]);
printf("%d\n",ans);
}
int main()
{
init();
return 0;
}