题目大意:给定n*m的木板,每个点需要刷成1和0两种颜色之一,每次只能刷一行中连续的一段,一个点只能刷一次,求T刷子最多能刷对多少个点
首先对每行拆开处理 令f[i][j]为用i刷子刷前j个格子最多刷对多少个点 动规处理出这一行刷i刷子最多能刷对多少个点 然后分组背包即可
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 60 using 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; }
原文地址:http://blog.csdn.net/popoqqq/article/details/40788815