5438.密病牛
题目链接:https://www.acwing.com/problem/content/description/5441/
题意:
每过一天病牛可以往左右扩散。
给定若干天后这群牛的状态,求最初的病牛最小个数
思路:
显然经过天数越多,病牛扩散的越厉害,最初需要的病牛数就越少。
所以先求经过最长天数:当最左边/右边有病牛时,res=cnt-1.否则,当cnt为奇数时,res=(cnt-1)/2,当cnt为偶数时,res=(cnt-2)/2,res取min,因为需要满足每过一天往左右扩散的条件
对于每堆病牛,一头病牛经过i天能最多使2*i+1(包括自己)生病,所以每堆计数一下cnt/(2*i+1)(向上取整)
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pb push_back
#define endl "\n"
#define fi first
#define se second
//#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const ll llmax=LLONG_MAX;
const int maxn=1e5+5;
const int mod=1e9+7;
int n;
string s;
signed main()
{
ios::sync_with_stdio(false),cin.tie(0);
cin>>n>>s;
int cnt=0;
int res=inf;
bool f=false;
rep(i,0,s.size()-1){
if(s[i]=='1'){
cnt++;
if(i==0)f=true;
}
if(s[i]=='0'&&cnt){
if(f){
f=false;
if(cnt%2==0){
res=min(res,cnt-1);
}else{
res=min(res,cnt-1);
}
}else{
if(cnt%2==0){
res=min(res,(cnt-2)/2);
}else{
res=min(res,(cnt-1)/2);
}
}
cnt=0;
}
}
if(cnt){
if(cnt%2==0){
res=min(res,cnt-1);
}else{
res=min(res,cnt-1);
}
}
cnt=0;
int ans=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
cnt++;
}
if(s[i]=='0'&&cnt){
ans+=(int)ceil(cnt*1.0/(2*res+1));
cnt=0;
}
}
if(cnt)ans+=(int)ceil(cnt*1.0/(2*res+1));
cout<<ans;
return 0;
}

浙公网安备 33010602011771号