题目链接: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;
}