2012 5 24 笨笨当粉刷匠

时间限制:
10000ms
内存限制:
128000kB
描述

笨笨太好玩了,农田荒芜了,彩奖用光了,笨笨只好到处找丁作,笨笨找到了一份粉刷匠的工作。笨笨有n条木板需要被粉刷。每条木板被分成m个格子,每个格子要被刷成红色或蓝色。笨笨每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色,已知每个格子最多只能被粉刷一次。

    如果笨笨只能粉刷t次,他最多能正确粉刷多少格子。

    一个格子如果未被粉刷或被粉刷成错误颜色,就算粉刷错误。

 

输入
第一行三个数n,m,t;
接下来n行,每行一个长度为m的字符“O”表示红色,“l”表示蓝色。
输出
一个整数,最多能正确粉刷的格子数。
样例输入
3 6 3
111111
000000
001100
样例输出
16
#include<iostream>
#include<algorithm>
#include<string.h>




using namespace std;

int f[55][55][2510][3];
int g[55][2501];
int h[55][2510];
int n,m,t;
char map[61][61];




int main( )
{
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=n;i++)
    {
       scanf("%s",map[i]+1);
    }
    for(int i=1;i<=n;i++)
    {
       for(int j=1;j<=m;j++)
       {
          map[i][j]-='0';
       }
    }
    memset(f,-1,sizeof(f));
    memset(g,-1,sizeof(g));
    memset(h,-1,sizeof(h));
    for(int a=1;a<=n;a++)
    {
       f[a][1][0][0]=f[a][1][0][1]=0;
       f[a][1][1][map[a][1]]=1;
       f[a][1][1][1-map[a][1]]=0;
       g[a][0]=0;
       g[a][1]=1;
       for(int b=2;b<=m;b++)
       {
          f[a][b][0][0]=f[a][b][0][1]=0;
          for(int c=1;c<=t;c++)
          {
             if(f[a][b-1][c][map[a][b]]!=-1)
             f[a][b][c][map[a][b]]=max(f[a][b][c][map[a][b]],f[a][b-1][c][map[a][b]]+1);
             if(c!=0&&f[a][b-1][c-1][0]!=-1)
             f[a][b][c][map[a][b]]=max(f[a][b][c][map[a][b]],f[a][b-1][c-1][0]+1);
             if(c!=0&&f[a][b-1][c-1][1]!=-1)
             f[a][b][c][map[a][b]]=max(f[a][b][c][map[a][b]],f[a][b-1][c-1][1]+1);
             if(f[a][b-1][c][1-map[a][b]]!=-1)
             f[a][b][c][1-map[a][b]]=max(f[a][b][c][1-map[a][b]],f[a][b-1][c][1-map[a][b]]);
             if(c!=0&&f[a][b-1][c-1][0]!=-1)
             f[a][b][c][1-map[a][b]]=max(f[a][b][c][1-map[a][b]],f[a][b-1][c-1][0]);
             if(c!=0&&f[a][b-1][c-1][1]!=-1)
             f[a][b][c][1-map[a][b]]=max(f[a][b][c][1-map[a][b]],f[a][b-1][c-1][1]);
             g[a][c]=max(max(g[a][c],f[a][b][c][0]),f[a][b][c][1]);
          }
       }
    }
    h[0][t]=0;
    int ans=-1;
    for(int a=1;a<=n;a++)
    {
       for(int b=0;b<=t;b++)
       {
          for(int c=b;c<=t;c++)
          {
             if(h[a-1][c]!=-1)
             {
                h[a][c-b]=max(h[a][c-b],h[a-1][c]+g[a][b]);
                ans=max(ans,h[a][c-b]);
             }
          }
       }
    }
    printf("%d\n",ans);
    return 0;
}

 这是道对我来说比较有深度的DP题,先对每行做处理,分情况对当前点是1或0进行讨论,最后再做一个01背包,可以出解。注意该题状态的划分。

原文地址:https://www.cnblogs.com/spwkx/p/2518587.html