题目来源:中山纪念中学
题目描述:
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;
}
提示:
慎开多维数组,注意空间溢出,多学学如何优化程序,包括空间优化和时间优化