C. Social Distance(暴力,贪心)

C. Social Distance

题意:
给出一个n, k和一个长度为n的只包含01的字符串。每两个1之间至少相隔k,问最多能够将几个0改成1。

贪心策略:
我们在两1之间求有多少个位置是能够将0改1的。因为在两个1之间,所以既要满足左边相隔k(至少),也有要满足右边相隔k。我们先去掉右边必须空掉的0,这样一来我们就只需考虑 前 面 1 的 位 置 前面1的位置 1 要 改 成 1 的 位 置 要改成1的位置 1的距离。等同于每个1往前带k个0,便于计算。
例子:k = 2,10000000001,加黑部分为可选位置。再每个k+1个位置可以改一个1,就可以改2个位置。

思路:
暴力枚举,记录每个1出现的位置和1的总个数u。
在用贪心策略时应该考虑没有1的情况,只有一个1的情况,和在头尾1的情况。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
char s[N];
int m[N];
int main() {
    
    
	int t, n, k, u, v, sum;
	scanf("%d", &t);
	while(t--) {
    
    
		 u = 0, sum = 0;
		scanf("%d%d", &n, &k);
		scanf("%s", s);
		for(int i=0; s[i]; i++) {
    
    
			if(s[i] == '1') 
			m[u++] = i;//记录1的下标
		}
		if(u == 0) {
    
    //没有1的情况
			sum += 1;
			sum += (n-1)/(k+1);
			printf("%d\n", sum);
		} 
		else if(u == 1) {
    
    //只要一个1的情况.
			sum += m[0]/(k+1);
			sum += (n-1-m[0])/(k+1);
			printf("%d\n", sum);
		}
		else {
    
    //有多个一的情况
			for(int i=0; i<u; i++) {
    
    
				if(i == 0) {
    
    //第一个1.
					sum += m[i]/(k+1);
					v = m[i+1]-m[i]-1-k;
					sum += v/(k+1);
				}
				if(i == u-1) {
    
    //最后一个1
					sum += (n-1-m[i])/(k+1);
				}
				if(i != 0 && i != u-1){
    
    //中间的1
					v = m[i+1]-m[i]-1-k;//计算可选0的个数
					sum += v/(k+1);//每k+1个0可以改一个1
				}
			}
			printf("%d\n", sum);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45363113/article/details/106878802