思维+贪心B. Saving the City
解题思路
如果只有 1 1 1 个连续 1 1 1 的区域,输出 a a a。否则从第二个连续1的区域开始贪心地考虑:是直接引爆自己 ( a ) (a) (a),还是把左边和自己中间填满之后引爆 ( n × b ) (n × b) (n×b)。
注意事项
1.虽然题目中说输入是 a string consisting of zeros and ones
,但是是有可能输入全 0 0 0 的数据的。所以最后输出的时候要判断有没有 1 1 1 。
2.如果是从第二个连续 1 1 1 的地方开始判断,要记得多加一个 a a a。
参考代码
#include<bits/stdc++.h>
using namespace std;
#define LOCAL //提交的时候一定注释
#define _for(i, a, b) for(int i = (a); i < (b); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define pb push_back
#define VI vector<int>
#define maxn 100010
#define INF 0x3f3f3f3f
typedef long long LL;
typedef double db;
const double eps = 1e-6; //定义浮点数误差
const int MOD = 998244353;
int readint(){
int x; scanf("%d", &x); return x;
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int t, n, a, b;
char str[maxn];
scanf("%d", &t);
while (t--) {
a = readint(); b = readint();
scanf("%s", str);
int one = 0, cnt = 0, res = 0;
bool find = false;
_for(i, 0, strlen(str)) {
//one |= str[i];
if (str[i] == '1') find = true;
if (str[i] == '0') {
if (find) cnt++; //如果之前出现过1了,说明接下来至少是第二个连续1的区域,需要判断
} else if (cnt > 0) {
//当前为1的时候,若左边有0,判断是否要连起来
res += (cnt * b < a) ? cnt * b : a;
cnt = 0; //重新开始计数
}
}
printf("%d\n", find ? res + a : res); //没出现过的话不用加上a
}
return 0;
}