BZOJ1296: [SCOI2009]粉刷匠(洛谷P4158)
阿新 • • 發佈:2018-12-19
DP
我連揹包都不會了
做兩遍DP,第一遍求出每一行刷次分別最多能刷對多少個格子。第二遍就把第一遍的當作分組揹包來選物品就好了。
設表示當前這行做到第列,刷了次的最多格子數。那麼有。其中分別為和的字首和。
分組揹包就不用說了吧。。。
程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 55
using namespace std;
int n,m,t,ans,s0[N],s1[N],f[N][N],g[N][N*N];
char s[N];
int main(){
scanf("%d%d%d",&n,&m,&t);
for (int i=1;i<=n;i++){
scanf("%s",s+1);
for (int j=1;j<=m;j++){
s0[j]=s0[ j-1],s1[j]=s1[j-1];
s[j]=='0'?s0[j]++:s1[j]++;
for (int k=0;k<=m;k++) f[j][k]=0;
}
for (int j=1;j<=m;j++)
for (int p=1;p<=j;p++)
for (int k=0;k<j;k++)
f[j][p]=max(f[j][p],f[k][p-1]+max(s0[j]-s0[k],s1[j]-s1[k]));
for (int j=1;j<=t;j++)
for (int k=0,p=min(m,j);k<=p;k++)
g[ i][j]=max(g[i][j],g[i-1][j-k]+f[m][k]);
}
for (int i=1;i<=t;i++) ans=max(ans,g[n][i]);
return printf("%d",ans),0;
}