题面
Cordell manages a row of seats at the Scuola Comunale di Musica Piova where students are strictly forbidden from sitting next to each other.
You are given a binary string , where indicates that the -th seat has been occupied by a student, and indicates that it is free now. It is guaranteed that no two adjacent seats are occupied currently. Cordell needs to add more students until it is impossible to seat anyone else in the row. However, she wants to achieve this state with as few students as possible.
Your task is to calculate the minimum total number of students seated when it is impossible to seat anyone else in the row.
A binary string is a string where each character is either or .
Input
Each test contains multiple test cases. The first line contains the number of test cases (). The description of the test cases follows.
The first line of each test case contains a single integer () — the number of seats in the row.
The second line of each test case contains the binary string of length (). It is guaranteed that no two adjacent characters are both .
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, output a single integer — the minimum total number of seated students.
思路
1 什么时候算无法再坐人
规则是不允许出现相邻的两个
如果某个位置是 且它左右相邻位置都不是 ,那么把它变成 仍然合法,说明还可以继续坐人
因此最终状态等价于:每个 的左右至少有一个位置是
换成字符串的局部形态就是 中间不能出现 且两端不能出现
2 把问题拆成若干段连续的
题目保证初始时没有相邻的 所以所有的 都是固定存在的学生
这些 会把整行座位切成若干段连续的 每段内部怎么加人不会影响别的段
所以答案可以写成
3 一段连续 最少要补多少个
考虑一段连续的 长度为
在这段里放入一个新学生 会占用一个位置 并且让它左右相邻位置都变成不可再放的位置
也就是一次放置最多覆盖连续三个位置的需求 因此每需要覆盖 个空位就要放一个学生
用哨兵统一讨论,令原串左右各加一个 方便找到每段 的左右端点
真实的边界需要单独修正,设:
其中 且方括号表示条件成立取 否则取
那么这一段的最少新增人数是:
这个式子对应三种常见情况
夹在两个 之间时 得到 贴一侧边界时 得到 两侧都是边界也就是整串全为 时 得到
4 扫描实现要点
从左到右扫描原串 统计已有的 直接加入答案
当遇到一个 段的起点 记录段左端点
当遇到一个 段的终点 计算 与 然后把 加到答案 判断是否贴边界可以用 表示贴左边界 用 表示贴右边界
代码
#include <bits/stdc++.h>
using namespace std;
int main() { int t; cin >> t; while (t --) { int n; string s; cin >> n >> s;
s = '1' + s + '1'; int ans = 0; int L = 0; for (int i = 1; i <= n; i ++) { if (s[i] == '0') { if (s[i - 1] == '1') L = i; if (s[i + 1] == '1') { int len = i - L + 1; int c = (L == 1) + (i == n); ans += (len + c) / 3; } } else { ans ++; } }
cout << ans << '\n'; } return 0;}*n*