给你一个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; }