BZOJ 1296 SCOI2009 粉刷匠 动态规划

来源:互联网 发布:2016淘宝知识产权扣分 编辑:程序博客网 时间:2024/04/29 01:42

题目大意:给定n*m的木板,每个点需要刷成1和0两种颜色之一,每次只能刷一行中连续的一段,一个点只能刷一次,求T刷子最多能刷对多少个点

首先对每行拆开处理 令f[i][j]为用i刷子刷前j个格子最多刷对多少个点 动规处理出这一行刷i刷子最多能刷对多少个点 然后分组背包即可

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 60using namespace std;int n,m,T,f[M][M];//f[i][j]表示用i刷子刷前j个格子能刷出的最多格子//f[i][j]=max{ f[i-1][k]+max(cnt[0],cnt[1]) }//(i-1<=k<=j-1)char s[M];int a[M][M];//a[i][j]表示第i行用j刷子能刷出的最大价值void DP(int pos){int i,j,k;memset(f,0xef,sizeof f);f[0][0]=0;for(i=1;i<=m;i++){for(j=i;j<=m;j++){int cnt[2]={0};for(k=j-1;k>=i-1;k--){cnt[s[k+1]-'0']++;f[i][j]=max(f[i][j],f[i-1][k]+max(cnt[0],cnt[1]));}}}for(i=1;i<=m;i++)a[pos][i]=f[i][m];}int Packet_Backpack(){int i,j,k;static int g[M][M*M];memset(g,0xef,sizeof g);g[0][0]=0;for(i=1;i<=n;i++)for(j=0;j<=m;j++)for(k=T;k>=j;k--)g[i][k]=max(g[i][k],g[i-1][k-j]+a[i][j]);return g[n][T];}int main(){int i;cin>>n>>m>>T;for(i=1;i<=n;i++){scanf("%s",s+1);DP(i);}cout<<Packet_Backpack()<<endl;}


0 0