题目描述
Farmer John 有 N 头奶牛排成一列(1<=N<=3*10^5)。不幸的是,有一种疾病正在传播。
最初,有一些奶牛被感染。每到夜晚,被感染的奶牛会将疾病传播给它左右两边的奶牛(如果这些奶牛存在的话)。一旦奶牛被感染,她就会持续处于感染状态。
经过一些晚上,Farmer John 意识到情况已经失控,因此他对奶牛进行了检测以确定哪些奶牛感染了疾病。请找出最少有多少头奶牛最初可能感染了这种疾病。
输入格式
第一行为一个整数 N,即 Farmer John 拥有的奶牛数量。
接下来一行,包含长度为 N 的由 1 和 0 组成的位串。其中 1 表示一头被感染的奶牛,0 表示一头在经过若干晚之后仍未被感染的奶牛。
输出格式
输出一个整数,表示最少有多少头奶牛可能最初感染了这种疾病。
样例输入 1
5
11111
样例输出 1
1
样例输入 2
6
011101
样例输出 2
4
样例解释 1
假设只有中间的奶牛最初被感染。那么,奶牛们将按以下顺序被感染:
- 第 0 晚:00100(第三只奶牛一开始被感染)
- 第 1 晚:01110(第二和第四只奶牛现在被感染了)
- 第 2 晚:11111(第一和第五只奶牛现在被感染了)
- 第 3 晚:11111(所有的奶牛都已经被感染了,没有新的奶牛被感染)
- ……
经过两个或更多的晚上,奶牛们的状态即与输入的状态相符。还有许多其他的初始状态和夜晚数量可能导致了输入的状态,例如:
- 第 0 晚:10001
- 第 1 晚:11011
- 第 2 晚:11111
或者:
- 第 0 晚:01001
- 第 1 晚:11111
或者:
- 第 0 晚:01000
- 第 1 晚:11100
- 第 2 晚:11110
- 第 3 晚:11111
所有这些初始状态中至少有一头奶牛被感染。
题目解析
#include <vector>
#include <iostream>
using namespace std;
vector<int> v;
int main() {
int n; //奶牛总数
string s; //最终感染情况
cin >> n >> s;
int pre = 0, suf = n - 1, cnt = 0, minDay = n + 1;
//pre和suf分别表示前和后的位置,cnt表示计数,minDay先设置为最坏情况的值
while (s[pre] == '1') {
pre++;
//cout <<"pre: "<< pre << endl;
}//从前往后
while (suf > pre && s[suf] == '1') {
suf--;
//cout<<"suf: " << suf << endl;
} //从后往前
if (pre != 0) { //
v.push_back(pre);
minDay = min(minDay, pre - 1);
}
if (suf != n - 1) {
v.push_back(n - 1 - suf);//最后一团奶牛数是n-1-suf
minDay = min(minDay, n - 2 - suf);//minDay就是n-2-suf
}
for (int i = pre; i <= suf; i++) {
if (s[i] == '1') cnt++;
else if (s[i] == '0') {
if (cnt > 0) {
v.push_back(cnt);
minDay = min(minDay, (cnt - 1) / 2);
}
cnt = 0;
}
}
if (cnt > 0) {
v.push_back(cnt);
minDay = min(minDay, (cnt - 1) / 2);
}
int ans = 0;
for (int i = 0; i < v.size(); i++) { //v.size()表示有多少团1
int k = v[i] / (minDay * 2 + 1); //minDay * 2 + 1 表示1头感染的奶牛通过minDay最多感染多少奶牛
if (v[i] % (minDay * 2 + 1)) k++; //计算当前向量元素 v[i] 对应的 0 的个数需要多少个初始 1 来覆盖
//如果当前 v[i] 不能被 (minDay * 2 + 1) 整除,说明有剩余的 0 需要额外的一个 1 来覆盖
ans += k;
}
cout << ans;
return 0;
}