黑子的鸡脚(doge)xtuoj1464

题目描述

输入输出样例

题目理解

题目要求我们在改变一个0为1的情况下,问最多能将原01串变为多少个长度为k的全1子串

首先我们要弄清这一个1最多能产生多大的影响

因为分割的子串是不相交的,假设某个0的分割效果最“明显”(也就是把它变为1效益最大)

它的左边在划分完所有可分为k长度的串之后,剩余k-1个1,右边同样有k-1个1,那将它变为1后,最多能让结果多几个k长的子串呢?

答案是1个,因为 k <k-1 + k-1 + 1<2k

既然如此,我们只要考虑什么情况下,我们可以在结果上加1即可

 情况分析

首先,毫无疑问,我们是采用遍历原01序列的办法统计每个被0分隔的全1子串的长度

某个0的左边和右边相加要大于等于k-1,才能满足在结果上可加1的条件

如何得到每个0左右的长度就是关键

在我们采用遍历统计的办法下,我们统计的目前长度记为cur,它可以表示成当前这个0的左边

但同时也可以表示成前一个0的右边,那么我们只需要多一个变量统计前一个0的左边即可

(因为现在这个0的右边,在我们下一次遇到0时便会被讨论进来)

这个变量记为before

那么我们每次遇到0时,开始讨论的格局应该如下所示

     11111111....                        0                11111111111...                            0                   11111...

 ↑长度为before的子串                              ↑长度为cur的子串               ↑当前位置

那么这道题最关键的部分代码也就可以写出来了

不要忘记:有0,才能有0变1的操作,0都没有的话何谈加1!

char fig[10010];
int a, k;
int solve() {
	bool f = false,z = false;//加一标志 ,有零标志
	int cur = 0, sum = 0, before = 0;
	for (int i = 0; fig[i] != '\0'; i++) {
		if (fig[i] == '0') {
			z = true;
			if (cur >= k)sum+=cur/k;

            //划分后剩下的其实就是对k取模
			if((before+cur%k)>=k-1)f = true;
			
            //可供下一次讨论利用的值也只有取模剩下的部分
            before = cur%k;
			cur = 0;
		} else cur++;
	}

    //如果序列不以0结尾,仍然要把统计的cur与before处理到结果当中
	if(cur)sum+=cur/k;
	if((!f)&&(cur%k+before>=k-1))f = true;

    //有0且满足加1条件,则返回的结果+1;否则返回原结果
	if(f&&z)return sum+1;
	return sum;
}

完整code

#include<iostream>
using namespace std;
char fig[10010];
int a, k;
int solve() {
	bool f = false,z = false;
	int cur = 0, sum = 0, before = 0;
	for (int i = 0; fig[i] != '\0'; i++) {
		if (fig[i] == '0') {
			z = true;
			if (cur >= k)sum+=cur/k;
			if((before+cur%k)>=k-1)f = true;
			before = cur%k;
			cur = 0;
		} else cur++;
	}
	if(cur)sum+=cur/k;
	if((!f)&&(cur%k+before>=k-1))f = true;
	if(f&&z)return sum+1;
	return sum;
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &a, &k);
		scanf("%s", fig);
		printf("%d\n", solve());
	}
}

题干中的鸡脚

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值