#dp#洛谷 4158 [SCOI2009]粉刷匠

题目


分析

首先每条木板可以分开处理,再合并起来求最大值
下面讲一下单独处理每条木板的情况
(dp[k][m])表示前(m)个格子粉刷了(k)次最多正确粉刷的格子数
那么

[dp[k][m]=max{dp[k-1][m']+(m-m'-(s[m]-s[m']))} ]


代码

#include <cstdio>
#include <cstring>
#define rr register
using namespace std;
const int N=51;
int n,m,T,ans,s[N],dp[N*N],f[N][N];
inline signed min(int a,int b){return a<b?a:b;}
inline signed max(int a,int b){return a>b?a:b;}
signed main(){
	scanf("%d%d%d",&n,&m,&T);
	for (rr int i=1;i<=n;++i){
		memset(f,0,sizeof(f));
	    for (rr int j=1;j<=m;++j){
		    rr char c=getchar();
		    while (c!=48&&c!=49) c=getchar();
	        s[j]=s[j-1]+(c^48);
		}
		for (rr int j=1;j<=m;++j)
		    for (rr int k=j;k<=m;++k)
		        for (rr int p=j-1;p<k;++p)
		            f[j][k]=max(f[j][k],f[j-1][p]+max(s[k]-s[p],k-p-s[k]+s[p]));
		for (rr int j=T;j>=1;--j)
		for (rr int k=min(j,m);~k;--k)
		    dp[j]=max(dp[j],dp[j-k]+f[k][m]);
	}
	for (rr int i=1;i<=T;++i) ans=max(ans,dp[i]);
	return !printf("%d",ans);
} 
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13821485.html