CodeChef 2017 March Challenge SCHEDULE - 烹饪计划

本文介绍了一种通过二分查找法优化大厨工作计划的算法。该算法旨在通过最少次数的修改,使得连续相同工作安排的天数达到最少。通过对连续相同安排的天数进行预处理,并使用二分法来确定最优解。
题目

大厨为接下来的 N 天定制了一个计划。在第 i 天,如果 Ai = 1,那么大厨会在那天工作;如果 Ai = 0,那么大厨就会休息。
大厨决定对这份计划做一些修改,最多修改 K 天的安排。大厨会选出最多 K 天,对于选出的每一天 i,如果 Ai = 1,则将其改成 0;否则将其改成 1。
修改之后应当保证,具有相同安排(即 Ai相等)的连续一段的日子天数最少。

题解
  1. 预处理出a[i]表示第i段连续相同的长度是多少。
  2. 二分答案lim,然后判断是否合法。
  3. 对于连续一段相同的,考虑不改变最左边和最右边的数,使当前段不会影响到相邻的段。那么我们每隔lim个数就改变一个数字,假如要改变最后一个数字,就变成改变倒数第二个数字以保证不改变最右边的数,这样一段需要改变的数字就是a[i]/(lim+1)判断一个总共改变数字的个数与k的关系即可。
  4. 但是当lim=1时不能保证不改变最左和最右的数,那么特判一下即可。
#include<bits/stdc++.h>
using namespace std;
char a[1000010];
int b[1000010],cnt,k,n;
bool check(int x)
{
	int s=0,i;
	for(i=1; i<=cnt; i++)
		s+=b[i]/(x+1);
	return s<=k;
}
int main()
{
	int t,i,l,r,ans,mid,x;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%s",&n,&k,a+1);
		cnt=1;
		b[1]=1;
		for(i=1; i<=n; i++)
		{
			if(a[i]==a[i-1]) b[cnt]++;
			else
			{
				cnt++;
				b[cnt]=1;
			}
		}
		x=0;
		for(i=1; i<=n; i++)
			if(a[i]-'0'==(i&1)) x++;
		if(x<=k||(n-x)<=k)
		{
			printf("1\n");
			continue;
		}
		l=2;
		r=n;
		ans=0;
		while(l<=r)
		{
			mid=(l+r)/2;
			if(check(mid)) r=mid-1,ans=mid;
			else l=mid+1;
		}
		printf("%d\n", ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值