题目链接: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;
}