关闭

Codevs 1744 格子染色

223人阅读 评论(0) 收藏 举报
分类:

1744 格子染色
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
有 n 条木板需要被粉刷。 每条木板被分为 m 个格子。 每个格子要被刷成红
色或蓝色。
输入描述 Input Description
Dizzy 每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。 如果 Dizzy 只能粉刷 t 次,他最多能正确粉刷多少格子? 一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
输出描述 Output Description
第一行包含三个整数,n m t。 接下来有n行,每行一个长度为m的字符串,’0’表
示红色,’1’表示蓝色。
样例输入 Sample Input
3 6 3
111111
000000
001100
样例输出 Sample Output
16
数据范围及提示 Data Size & Hint
1 ≤ n,m ≤ 50 ; 0 ≤ t ≤ 2500 。
分类标签 Tags
动态规划

/*
区间(划分?)DP+背包DP. 
f[i][j][k]表示刷k次刷到(i,j)的最大格子数.
o(nm^2t).
一开始考虑的东西太多然后写不出来orz.
预处理后我们枚举一个w,
这样就成了一个区间问题:
求[1,j]只需求[1,w]和[w+1,j](w<=j).
决策有三种:不刷,刷0,刷1. 
然后从小区间到大区间乱搞...... 
我们发现每一行都是独立的(方格取数类似).
最后只需要跑背包分配每行刷几次就阔以啦. 
*/
#include<iostream>
#include<cstdio>
#define MAXN 51
#define MAXM 2501
using namespace std;
int n,m,t,f[MAXN][MAXN][MAXM],sum[MAXN][MAXN][2],s[MAXN][MAXM];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(f=='-')f-=1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x*f;
}
void slove()
{
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        for(int k=1;k<=t;k++)
          for(int w=1;w<=j;w++)
            f[i][j][k]=max(f[i][j][k],f[i][w-1][k-1]+
              max(sum[i][j][0]-sum[i][w-1][0],sum[i][j][1]-sum[i][w-1][1]));
    for(int i=1;i<=n;i++)
      for(int j=1;j<=t;j++)
        for(int k=0;k<=j;k++)
        s[i][j]=max(s[i][j],s[i-1][j-k]+f[i][m][k]);
    printf("%d",s[n][t]);
    return;
}
int main()
{
    char ch;
    n=read(),m=read(),t=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>ch,ch-=48;
            sum[i][j][0]=sum[i][j-1][0];
            sum[i][j][1]=sum[i][j-1][1];
            sum[i][j][ch]++;
        }
    slove();
    return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:63980次
    • 积分:3856
    • 等级:
    • 排名:第9093名
    • 原创:335篇
    • 转载:3篇
    • 译文:0篇
    • 评论:12条
    New blog