靈茶之貪心模擬01
題目連結
https://codeforces.com/problemset/problem/1443/B
題目大意
輸入 T(≤\(10^5\)) 表示 T 組資料。所有資料的字串長度之和 ≤ \(10^5\)。
每組資料輸入 a(1≤a≤1000) b(1≤b≤1000) 和長度不超過 \(10^5\) 的 01 字串。
你可以花費 a,把一段連續的 1 變成 0。
也可以花費 b,把一個 0 變成 1。
上述兩種操作可以執行任意次。 輸出把所有 1 都變成 0 的最小花費。
題目思路
- 如果沒有1,就直接輸出0
- 考慮這樣的一部分:1110001111
- 我們有兩種方案
- ①將兩邊連續的1花費a變成0,總花費為2a
- ②將中間0花費 k * b 變成1,在花費a將1變成0,總花費為 kb + a
- 比較方案①與方案②,自然是選擇總花費最小的方案了
- 我們只需從左往右使用雙指標[left,right],找到兩段 1中間的那串0,考慮將這兩段1合併成一段1的最小花費,再加上最後合併成的那一連串1的花費a即可
程式碼
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n,a,b,t;
void solve() {
string s;
cin >> a >> b;cin >> s;
n = (int)s.size();
// s 裡 不 包 含 0!
if(s.find('1') == string::npos) {
cout << 0 << '\n';
return;
}
int ans = a;
int right = 0,left;
while(right < n){
char x = s[right];
left = right;
while(right < n && s[right] == x) ++right;
if(x == '0' && right < n){
if(left == 0) continue;
ans += min(b * (right - left),a);
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
for (int _ = 0; _ < t; _++) solve();
return 0;
}