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