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


posted @ 2025-02-26 15:47  Marinaco  阅读(21)  评论(0)    收藏  举报
//雪花飘落效果