/* * 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]转移过来。 * 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。 */ #include<bits/stdc++.h> using namespace std; const int maxn=1e6+100; int T; int N,K; string s; int pre[maxn]; int dp[maxn][2]; int main () { cin>>T; while (T--) { cin>>N>>K; for (int i=0;i<=N;i++) dp[i][0]=dp[i][1]=pre[i]=0; cin>>s; for (int i=1;i<=N;i++) pre[i]=pre[i-1]+(s[i-1]=='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]=='1'); dp[i][1]=min(dp[p][1]+pre[i-1]-pre[p],pre[i-1])+(s[i-1]=='0'); } printf("%d ",min(dp[N][0],dp[N][1])); } }