https://codeforces.com/problemset/problem/225/C
题意:给出一个矩阵,包含两种颜色,问最少修改多少个点才能让每一列的颜色一致,且颜色一致的连续的列的长度在x和y之间。
思路:
dp[i][j][0/1]:到第i个,且连续j个数字的,当前为#/.的最小花费。
j==1的时候dp[i][1][0/1]=min(dp[i][t(x~y)][1/0])
j!=1,dp[i][j][0/1]=min(dp[i-1][j-1][0/1]);
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e3+100;
typedef int LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL add1[maxn],add2[maxn];
char str[maxn][maxn];
LL dp[maxn][maxn][2];
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,m,x,y;cin>>n>>m>>x>>y;
for(LL i=1;i<=n;i++){
for(LL j=1;j<=m;j++) cin>>str[i][j];
}
for(LL j=1;j<=m;j++){
for(LL i=1;i<=n;i++){
add1[j]+=(str[i][j]=='.');
add2[j]+=(str[i][j]=='#');
}
}
memset(dp,0x3f,sizeof(dp));
dp[1][1][0]=add1[1];
dp[1][1][1]=add2[1];
for(LL i=2;i<=m;i++){
for(LL t=x;t<=y;t++){
dp[i][1][0]=min(dp[i][1][0],dp[i-1][t][1]+add1[i]);
dp[i][1][1]=min(dp[i][1][1],dp[i-1][t][0]+add2[i]);
}
for(LL j=2;j<=y;j++){
dp[i][j][0]=min(dp[i][j][0],dp[i-1][j-1][0]+add1[i]);
dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][1]+add2[i]);
}
}
LL ans=0x3f3f3f3f;
for(LL j=x;j<=y;j++){
ans=min(ans,dp[m][j][0]);
ans=min(ans,dp[m][j][1]);
}
cout<<ans<<"\n";
return 0;
}