USACO/DEC/BR2

P9975 [USACO23DEC] Cowntact Tracing 2 B

题目传送门

分析

需要求最少可能感染的牛,知道最终情况,那我们想一下影响感染的因素除了牛的数量还有什么?

牛的位置,感染的天数

那我们可以试试这两个能否得到?

可以发现感染的牛放中间位置就是扩散最快的,但是每个感染的牛放偏中间就是最优解吗?例如$ 1110111110 $ ,一个放最左一个放中间,发现并不可以

那感染的天数呢?如果我希望放的牛少,但是感染的牛多,应该希望感染的天数越多越好,我们能知道可能感染的最大天数吗?好像可以每个感染的区域只放1头牛在中间,但是我们发现头尾的区域希望感染的久应该放两端点,偶数感染的区域要放2头在中间

知道可能感染的最大天数后,我们就可以试着把感染的区域放上最初的牛,位置怎么放呢?如果感染1天1个区域放2头情况可能是 \(111111\)\(011111\)\(011110\) ,就是1头牛的最优位置,在考虑第2头牛怎么放\(d\)为天数,\(t\)为区域感染牛的数,$d*2+1 $就为1头牛的最优摆放位置,那 \(t\%(d*2+1)==0\),就代表有 \(t/(d*2+1)\) 牛,都在最佳位置否则 +1,表示1头牛不在最优位置

头尾特判,正好等于天数就表示左右端点开始,否则也是同上

AC code

#include <bits/stdc++.h>
using namespace std;
//牛最小值 -> 传播天数多
//求每组连续感染的牛所需最多天数
//前后特判  偶数特判 
int hel(int a,int b){
	if(a%b==0) return a/b;
	else return a/b+1;
}
int main(){
	int n,t=0;
	string s;
	cin >> n >> s;
	int minn = 1e9;
	//连续段的最大天数 
	int l = 0,r = n-1;
	for(;l<=n-1;l++){
		if(s[l]=='0') break;
	}
	for(;r>=0;r--){
		if(s[r]=='0') break;
	}
	if(l==n){
		cout << 1;
		return 0;
	}
//	cout << l << " " << r << endl;
	//最大天数 
	if(l-1>=0) minn = min(l-1,minn);
	if(n-2-r>=0) minn = min(n-2-r,minn);
	for(int i=l;i<=r;i++){
		if(s[i]=='1') t++;
		else{
			if(t==0) continue;
			if(t%2==0) minn = min(minn,(t-1)/2);
			else minn = min(minn,t/2);
			t = 0;
		}
	}
//	cout << "最大天数" << minn << endl; 
	//填感染的牛 
	int ans = 0;
	//头尾特判 等于最大天数就加 1,否则按最优策略
	for(int i=0;i<=l;i++){
		if(s[i]=='1') t++;
		else{
			if(t==0) continue;
			if(t==minn+1){
				ans++;
				t=0;
				break;
			}
			ans += hel(t,minn*2+1);
			t = 0;
		}
	}
	for(int i=n-1;i>=r;i--){
		if(s[i]=='1') t++;
		else{
			if(t==0) continue;
			if(t==minn+1){
				ans++;
				t=0;
				break;
			}
			ans += hel(t,minn*2+1);
			t = 0;
		}
	}
//	cout << "ans头尾" << ans << endl; 
	//除头尾
	for(int i=l;i<=r;i++){
		if(s[i]=='1') t++;
		else{
			if(t==0) continue;
			ans += hel(t,minn*2+1);
			t = 0;
		}
	}
	cout << ans;
	return 0; 
}
posted @ 2023-12-21 14:52  Nijika  阅读(35)  评论(0)    收藏  举报