cf-Enduring Exodus

 Enduring Exodus

参考自点击打开链接

题目点击打开链接

题意:
    一个农夫带着k头牛去住店,(人一间,每牛一间)已知该旅店共有n间房,其中部分房间已有人住,房间住宿情况由01串表示,0表示空,1表示已有人住,剩余房间足够容纳(k+1)头牛/人。为了保障牛的安全,希望人住的房间离最远的牛的房间位置尽量小,输出最小距离。


思路:
    很明显为了让人住的离最远的牛最近,那么最后这批人牛住的房间肯定是连续的(不算原有的住宿人员),且人住的位置离中心点越近越好。首先,枚举住宿的左区间,如果左端点已有人住,则跳过该点,如果空,则二分以该点为左端点,空闲房间数为k+1的最左位置。随后在这个区间内,开始寻找空闲的最中心位置(距离远的那端尽量小),利用区间长度奇偶性设置两个指针p1,p2的初始位置,随后分别往两端移动,因为一定有空闲位置,且两指针同时移动,不会出现越界情况。最后找到一个解,则计算最远距离,若小于最优值,则更新。

#include <algorithm>
#include <cstring>
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include<cmath>
#define MAX 100005
using namespace std;
int main(){
	int n,k,ans;
	char b[MAX];
	int s[MAX]; 
cin>>n>>k;
scanf("%s",b+1);
s[0]=0;
for(int i=1;i<=n;i++){
	
	s[i]=s[i-1]+(b[i]=='0'?1:0);//s[1]=1,s[2]=1,s[3]=2,
	}                     //s[4]=3,s[5]=3,s[6]=4,s[7]=5
	ans=MAX*10;           //1123345
	for(int i=1;i<=n;i++){//0100100
	                      //1011011b[i]
	                      //1234567
		if(b[i]=='1')
		continue;
		int l=1,r=n;//l=1,r=7||l=1,r=4
		while(l<r){
			int mid=(l+r)/2;//mid=4,mid=2
			int ml=max(l,i-mid);//ml=1,ml=1
			int mr=min(n,i+mid);//mr=4,mr=2
			if(s[mr]-s[ml-1]-1>=k){//= 
				r=mid;
			}
			else{
				l=mid+1;//l=3
			}
		}
		ans=min(ans,l);
	}

	cout<<ans<<endl;

	return 0;
} 
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include<cmath>
#define MAX 100005
using namespace std;
	int n,k,ans;
	int sum[MAX];
	char s[MAX];
	int judge(int mid){
		for(int i=1;i<=n;i++){
			if(s[i]=='1') continue;
			int L=max(i-mid,L);
			int r=min(i+mid,n);
			if(sum[r]-sum[L-1]-1>=k)
			return 1;
		}
		return 0;
	}
int main(){
 cin>>n>>k;
scanf("%s",s+1);
 for(int i=1;i<=n;i++){
 	sum[i]=sum[i-1];
 	if(s[i]=='0')
 	sum[i]++;
 } 
 int L=0,r=n,mid;
 ans=0;
 while(L<=r){
 	mid=(L+r)/2;
 	if(judge(mid)){
 		r=mid-1,ans=mid;
	}
 		else
 		L=mid+1;
	 
 }
 cout<<ans<<endl;
 return 0;
}







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值