题目:
windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
思路:
dp题目啊。
怎么想到的?恩。。。。感觉这个状态可以从上一个转移。
两边dp:
第一遍dp横向的
f[i][j]表示前i个格子染色t次正确的最大值。
f[i][j]=max(f[i][j],f[k][j-1]+max(sum[i]-sum[k],k-p-(sum[i]-sum[k]));
再dp纵向的。
dp[i][j]表示前i行染j次
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]
有个要注意的循环。。键代码
/**************************************************************
Problem: 1296
User: mars_ch
Language: C++
Result: Accepted
Time:2180 ms
Memory:1820 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//by mars_ch
int n,m,t;
int f[51][2505],dp[51][2505];
char s[55],sum[55];
int main()
{
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
for(int j=0;j<m;j++)
{
sum[j+1]=sum[j]+(s[j] -'0');
}
memset(f,0,sizeof(f));
f[1][1]=1;
for(int j=1;j<=m;j++)
{
for(int k=1;k<=t;k++)
{
for(int p=0;p<=j;p++) //要从0开始,不是1
{
f[j][k]=max(f[j][k],f[p][k-1]+max(sum[j]-sum[p],j-p-sum[j]+sum[p]));
}
}
}
/*for(int j=1;j<=m;j++)
{
for(int k=1;k<=t;k++)
{
printf("%d ",f[j][k]);
}
puts("");
}*/
for(int j=1;j<=t;j++)
{
for(int k=1;k<=j;k++)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+f[m][k]);
}
}
}
printf("%d\n",dp[n][t]);
return 0;
}