题目来源:中山纪念中学

题目描述:

windy有 N 条木板需要被粉刷。
每条木板被分为 M 个格子。
每个格子要被刷成红色或蓝色。
windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。
每个格子最多只能被粉刷一次。
如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。

输入:

第一行包含三个整数,N M T。
接下来有N行,每行一个长度为M的字符串,'0’表示红色,'1’表示蓝色。

输出:

输出一个整数,表示最多能正确粉刷的格子数。

输入样例:

3 6 3
111111
000000
001100

输出样例:

16

数据范围:

100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500

思路:动态规划

设f[i][j][k][l]表示前i块木板前j个格子粉刷k次,颜色为l最多能正确粉刷的格子数,然后分三种情况讨论:
1、当前格子为当前木板的第一格,要从上一块木板转移
2、当前格子与前一个格子颜色相同
3、当前格子与前一个格子颜色不同

AC代码:

/* 设f[i][j][k][l]表示前i块木板前j个格子粉刷k次,颜色为l最多能正确粉刷的格子数 */
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,t,f[51][51][2500][2];
char a[51][51];
int main()
{
	scanf("%d%d%d",&n,&m,&t);
	for (int i=1;i<=n;i++) scanf("%s",a[i]+1);
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=m;j++)
	    for (int k=1;k<=t;k++)
	    {
	    	if (j==1) //当前木板的第一个格子
			{
				f[i][j][k][0]=max(f[i-1][m][k-1][0],f[i-1][m][k-1][1])+(a[i][j]=='0');
				f[i][j][k][1]=max(f[i-1][m][k-1][0],f[i-1][m][k-1][1])+(a[i][j]=='1');
			} 
			else
			{
				f[i][j][k][0]=max(f[i][j-1][k][0],f[i][j-1][k-1][1])+(a[i][j]=='0');
				f[i][j][k][1]=max(f[i][j-1][k][1],f[i][j-1][k-1][0])+(a[i][j]=='1');
			}
		}
	int anss=0;
	for (int i=1;i<=t;i++) 
	  anss=max(anss,max(f[n][m][i][1],f[n][m][i][0]));
	printf("%d\n",anss);
	return 0;
}

提示:

慎开多维数组,注意空间溢出,多学学如何优化程序,包括空间优化和时间优化

佛系镇楼: