【DP】E. K-periodic Garland

E. K-periodic Garland

题意:给定长度为n的01字符串,每次操作可以改变一个字符的状态,问使字符串中相邻1的距离为k的最小操作次数

思路:

DP。

\(pre[i]\)记录前\(i\)项中\(1\)的个数

\(dp[i][0]\)为使得前\(i\)项都合法,第\(i\)位为\(0\)时的最小操作次数

\(dp[i][1]\)为使得前\(i\)项都合法,第\(i\)位为\(1\)时的最小操作次数

那么转移方程

$dp[i][0]=min(dp[i-1][0],dp[i-1][1])+(s[i]==1) $

因为第\(i\)项为\(0\)时对合法性无影响,其合法性可以直接从\(dp[i-1][0]或者dp[i-1][1]\)转移过来,操作次数更新由\(s[i]==1\)负责,若\(s[i]\)本身就为0,则新增0次操作,否则新增1次操作

\(dp[i][1]=min(dp[i-k][1]+pre[i-1]-pre[i-k],pre[i-1])+(s[i]==0)\)

当第\(i-k\)项合法时,要使第\(i\)项为\(1\)时合法,则要保证第\(i-k+1\)项到第\(i-1\)项都为\(0\),第\(i\)项才能为\(1\)(此时\(pre[i-1]-pre[i-k]=0\)),\(dp[i][1]\)的状态才能从\(dp[i-k][1]\)转移过来;或者从“令\(1\)\(i-1\)项全为\(0\),使得第\(i\)项为整个序列的第一个\(1\)”的状态转移过来。操作次数更新由\(s[i]==0\)负责,若\(s[i]\)本身就为1,则新增0次操作,否则新增1次操作

最后注意输入的是字符数组

void solve() {
	int n, k;
	cin >> n >> k;
	cin >> s+1;
	for (int i = 1; i <= n; i++)
		pre[i] = pre[i - 1] + (s[i] == '1');
	for (int i = 1; i <= n; i++) {
		int p = max(0, i - k);
		dp[i][0] = min(dp[i - 1][0], dp[i - 1][1]) + (s[i] == '1');
		dp[i][1] = min(dp[p][1] + pre[i - 1] - pre[p], pre[i - 1]) + (s[i] == '0');
	}
	cout << min(dp[n][0], dp[n][1]) << endl;
	for (int i = 0; i <= n; i++) {
		dp[i][1] = 0;
		dp[i][0] = 0;
		pre[i] = 0;
	}
}
posted @ 2020-05-15 20:30  StreamAzure  阅读(368)  评论(2编辑  收藏  举报