题目链接:https://codeforces.com/problemset/problem/225/C
题目大意:
您有一张n  ×  m像素的图片。每个像素可以是白色或黑色。您的任务是更改尽可能少的像素颜色以获得条形码图片。

如果满足以下条件,则图片为条形码:

1.每列中的所有像素均具有相同的颜色。
2.每条单色垂直线的宽度至少为x,最多为y个像素。换句话说,如果我们用相同的颜色对像素的所有相邻列进行分组,则每个组的大小不能小于x或大于y。

思路:我们可以用f[i][2]:
f[i][1]:第i列染黑色的更改尽可能少的像素颜色。
f[i][0]:第i列染白色的更改尽可能少的像素颜色。

我们考虑转移:

如果i染黑色,那么包含i列的前面J列都必须染成黑色。枚举J。
同理:i染白色也一样。s[i]:黑色像素方块的第i列的前缀和。

#include <bits/stdc++.h>
#define LL long long
using namespace std;

int a[1005][1005];
int s[1005];
char c[1005];
int f[1005][2];
int main(){

    memset(f, 7, sizeof(f));
    f[0][0]=f[0][1]=0;
    int n, m, x, y;
    scanf("%d%d%d%d", &n, &m, &x, &y);
    for(int i=1; i<=n; i++){
        scanf("%s", c+1);
        for(int j=1; j<=m; j++){
            a[i][j]=(c[j]=='#'?1:0);
        }
    }
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            s[i]+=a[j][i];
        }
        s[i]+=s[i-1];
    }
    for(int i=x; i<=m; i++){
        for(int j=x; j<=y; j++){//连续块数
            if(i-j>=0){
                f[i][0]=min(f[i][0], f[i-j][1]+(s[i]-s[i-j]));
                f[i][1]=min(f[i][1], f[i-j][0]+n*(j)-(s[i]-s[i-j]));
            }
        }
    }
    printf("%d\n", min(f[m][0], f[m][1]));

    return 0;
}