[luoguP1947] 笨笨当粉刷匠_NOI导刊2011提高(10)(DP)

传送门

 

f[i][j][k]表示前i行,最后一行前j个,选k次最优解

ntr[i][j][2]表示当前行区间i~j涂0或1所能刷的正确格子

 

#include <cstdio>
#define N 51
#define M 2501
#define max(x, y) ((x) > (y) ? (x) : (y))

char s[N];
int n, m, t, ans;
int ntr[N][N][2], f[N][N][M];
//f[i][j][k]表示前i行,最后一行前j个,选了k次的最优解

int main()
{
	int i, j, k, l;
	scanf("%d %d %d", &n, &m, &t);
	for(i = 1; i <= n; i++)
	{
		scanf("%s", s + 1);
		for(j = 1; j <= m; j++)
			for(k = j; k <= m; k++)
			{
				ntr[j][k][0] = ntr[j][k - 1][0] + (s[k] == '0');
				ntr[j][k][1] = ntr[j][k - 1][1] + (s[k] == '1');
			}
		for(j = 0; j <= m; j++)
			for(k = 1; k <= t; k++)
			{
				f[i][j][k] = !j ? f[i - 1][m][k] : f[i][j - 1][k];
				for(l = 0; l < j; l++)
				{
					f[i][j][k] = max(f[i][j][k], f[i][l][k - 1] + ntr[l + 1][j][0]);
					f[i][j][k] = max(f[i][j][k], f[i][l][k - 1] + ntr[l + 1][j][1]);
				}
				ans = max(ans, f[i][j][k]);
			}
	}
	printf("%d\n", ans);
	return 0;
}

  

posted @ 2017-08-10 19:47  zht467  阅读(165)  评论(0编辑  收藏  举报