题意:
给你一个长度为 n n n 的 01 01 01 字符串和一个整数 k k k,每次操作你可以选择一个字符并改变其状态,要使字符串中相邻 1 1 1 的距离为 k k k,问最少需要操作几次。
- 当前 i − 1 i - 1 i−1 项合法时,第 i i i 项为 0 0 0 ,那么前 i i i 项必定合法
- 当前 i − k i - k i−k 项合法时,第 i 项为 1 ,那么仅当第 i − k i - k i−k 为 1 1 1,且 i − k + 1 , i − 1 i - k + 1 , i - 1 i−k+1,i−1 项为 0 0 0 时,前 i i i 项合法。
AC代码:
const int N = 1e6 + 50;
int pre[N]; // pre[i] 为前 i 项 1 的个数
int dp[N][2]; //dp[i][0] 为前 i 项都合法 , 第 i 位为 0 的最小操作次数
//dp[i][1] 为前 i 项都合法 , 第 i 位为 1 的最小操作次数
char s[N];
int main()
{
int t;
sd(t);
while (t--)
{
int n, k;
sdd(n, k);
ss(s + 1);
rep(i, 0, n)
dp[i][0] = dp[i][1] = pre[i] = 0;
rep(i, 1, n)
pre[i] = pre[i - 1] + s[i] - '0';
rep(i, 1, n)
{
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(pre[i - 1], dp[p][1] + pre[i - 1] - pre[p]) + (s[i] == '0');
}
pd(min(dp[n][0], dp[n][1]));
}
return 0;
}