CF225C 题解

思路

s0is0_i 表示第 ii 列中 . 的个数(此处不是 #,因为全改成 # 需要修改 . 的个数的代价),s1is1_i 表示第 ii 列中 # 的个数,dpi,j,kdp_{i,j,k} 表示最后一列是第 ii 列且最后一列选了 kk,已经连续相同了 jj 列时的最小代价(00 表示 #11 表示 .)。dpi,1,kdp_{i,1,k} 可以从 dpi1,lr,¬kdp_{i-1,l\sim r,\neg k} 转移过来,dpi,j,kdp_{i,j,k} 可以从 dpi1,j1,kdp_{i-1,j-1,k} 转移过来。最终结果就是 min(dpn,lr,01)\min(dp_{n,l\sim r,0\sim1})

代码

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
int n, m, l, r, dp[1005][1005][2], a[1005][2], minx = 1e9;
string s;
int main () {
	ios::sync_with_stdio (0);
	cin.tie (0);
	cout.tie (0);
	cin >> n >> m >> l >> r;
	for (int i = 0; i < n; ++ i) {
		cin >> s;
		for (int j = 0; j < m;)
			if (s[j] ^ '#')
				++ a[++ j][0];
			else
				++ a[++ j][1];
	}
	memset (dp, 0x3f, sizeof dp);
	dp[0][0][0] = dp[0][0][1] = 0;
	for (int i = 1; i <= m; ++ i) {
		for (int j = l; j <= r; ++ j)
			for (int k = 0; k < 2; ++ k)
				dp[i][1][k] = min (dp[i][1][k], dp[i - 1][j][! k] + a[i][k]);
		for (int j = 1; j <= r; ++ j)
			for (int k = 0; k < 2; ++ k)
				dp[i][j][k] = min (dp[i][j][k], dp[i - 1][j - 1][k] + a[i][k]);
	}
	for (int j = l; j <= r; ++ j)
		for (int k = 0; k < 2; ++ k)
			minx = min (minx, dp[m][j][k]);
	cout << minx;
	return 0;
}
posted @ 2024-05-07 15:24  Vitamin_B  阅读(11)  评论(0)    收藏  举报  来源