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

浙公网安备 33010602011771号