给你一个NM的矩阵,其中有白色和黑色两种颜色,我们可以将其中的任意格子颜色变成另外一种颜色,问最少操作多少次(变换颜色),使得这个NM的矩阵变成一个条形码,并且保证相同颜色挨在一起的列数不小于x不大于y、(条形码|||||||)

dp[i][0]表示以0为结尾合法的最小染色数
dp[i][1]表示以1为结尾合法的最小染色数

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
char str[maxn];
int a[maxn][maxn];
int sum[maxn][2];
int dp[maxn][2];
int main() {
    int n, m, x, y;
    scanf("%d%d%d%d", &n, &m, &x, &y);
    for (int i = 1; i<= n; i++) {
        scanf("%s", str + 1);
        for (int j = 1; j <= m; j++) {
            if (str[j] == '#') sum[j][0]++; 
            if (str[j] == '.') sum[j][1]++;
        }
    }
    for (int i = 1; i <= m; i++) {
        sum[i][0] += sum[i - 1][0]; 
        sum[i][1] += sum[i - 1][1];
    }
    memset(dp, 30, sizeof(dp));
    dp[0][0] = 0;
    dp[0][1] = 0;
    for (int i = 1; i <= m; i++) {
        for (int j = x; j <= y; j++) {
            //注意,因为该区间已经全部染成同一种颜色,所以,前面的颜色必须与当前颜色不同,否则会产生错误(会产生同颜色超过y的情况)
            if (i - j >= 0)dp[i][0] = min(dp[i][0], dp[i - j][1] + sum[i][1] - sum[i - j][1]); 
            if (i - j >= 0)dp[i][1] = min(dp[i][1], dp[i - j][0] + sum[i][0] - sum[i - j][0]);

        }    
//        cout << dp[i][0] << " " << dp[i][1] << endl;
    }
    cout << min(dp[m][0], dp[m][1]) << endl;
    return 0;
}