社交距离

【问题描述】
一种新型疾病,COWVID-19,开始在全世界的奶牛之间传播。Farmer John 正在采取尽可能多的预防措施来防止他的牛群被感染。
Farmer John 的牛棚是一个狭长的建筑物,有一排共 N 个牛栏(2≤N≤10^5)。有些牛栏里目前有奶牛,有些目前空着。
得知“社交距离”的重要性,Farmer John 希望使得 D 尽可能大,其中 D 为最近的两个有奶牛的牛栏的距离。例如,如果牛栏 3 和 8 是最近的有奶牛的牛栏,那么 D=5。

最近两头奶牛新来到 Farmer John 的牛群,他需要决定将她们分配到哪两个之前空着的牛栏。
请求出他如何放置这两头新来的奶牛,使得 D 仍然尽可能大。Farmer John 不能移动任何已有的奶牛;他只想要给新来的奶牛分配牛栏。

【输入】
输入的第一行包含 N。下一行包含一个长为 N 的字符串,由 0 和 1 组成,描述牛棚里的牛栏。0 表示空着的牛栏,1 表示有奶牛的牛栏。
字符串中包含至少两个 0,所以有至少有足够的空间安置两头新来的奶牛。

【输出】
输出 Farmer John 以最优方案在加入两头新来的奶牛后可以达到的最大 D 值(最近的有奶牛的牛栏之间的距离)。

【输入样例】
14
10001001000010

【输出样例】
2

【算法分析】
暴力的做法可以枚举两个'0'位置,插入新奶牛,但要超时。
线性做法,可以寻找最大空隙尝试插入一头或两头奶牛,但讨论的情况很多,比如两段没有奶牛,一开始一只奶牛都没等特殊情况。
相对好的做法是二分答案,先计算未插入奶牛前的最小距离r,然后设l=1,二分答案范围在[l,r]。
判断答案x,可以设一个变量p,表示上一头奶牛的位置,如果p+x+x<=a[i](a[i]表示第i头奶牛位置),则p+x位置可以插入新奶牛
初始p=1-x,即第一个尝试新奶牛的位置是1。最后一头奶牛位置a[m]+x<=n,也可以尝试插入奶牛。
如果插入奶牛数量大于等于2,则表示x可以成为答案。

【算法代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m,ans;
int a[maxn];
char s[maxn];

int chk(int x) {
	int p=1-x,cnt=0;
	for(int i=1; i<=m; i++) {
		while(p+x+x<=a[i]) p+=x,cnt++; //p+x放新奶牛
		p=a[i];
	}
	while(p+x<=n) p+=x,cnt++;
	return cnt>=2;
}

int main() {
	cin>>n;
	cin>>s+1;
	for(int i=1; i<=n; i++)
		if(s[i]=='1') a[++m]=i;
	int l=1,r=n;
	for(int i=1; i<m; i++) r=min(r,a[i+1]-a[i]);
	while(l<=r) {
		int mid=l+r>>1;
		if(chk(mid)) {
			ans=mid;
			l=mid+1;
		} else r=mid-1;
	}
	cout<<ans;
	return 0;
}


/*
input:
14
10001001000010

output:
2
*/

 

【参考文献】
https://www.acwing.com/problem/content/1661/
https://blog.csdn.net/dglyr/article/details/105693645
https://www.it610.com/article/1294019983889735680.htm
https://mp.weixin.qq.com/s/S-ZmJupwvRF98cRTuqO1Lw


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值