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; }