[Luogu] CF1443B Saving the City
阿新 • • 發佈:2020-11-21
Description
你有一段\(01\)串,你可以選擇花費\(B\)的代價將一個\(0\)變為\(1\),也可以花費\(A\)的代價將一段連續的\(1\)變為\(0\),問你最少需要多少代價,才能把整個串都變為\(0\)。
Solution
這道題其實不太像\(DP\)。
會發現無論對當前點做什麼操作,都不會會後麵點的選擇有影響,即無後效性。
所以對於一段連續的\(1\),我們在最後一個點考慮把它全部消掉的代價。可以用\(A\)直接消掉,也可以把它和下一段連續的\(1\)一起消掉,這時花費為把它們中間的\(0\)都推平的代價(即\(len\times{B}\))。
這樣考慮一定是對的。因為對於下一段連續的\(1\)
要注意判斷這一段\(1\)後面沒有\(1\)的情況。
Code
#include <bits/stdc++.h> using namespace std; int t, a, b; char ch[100005]; int read() { int x = 0, fl = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();} while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();} return x * fl; } int main() { t = read(); while (t -- ) { a = read(); b = read(); scanf("%s", ch + 1); int l = strlen(ch + 1), res = 0; for (int i = 1; i <= l; i ++ ) { if ((ch[i] == '1' && ch[i + 1] == '0') || (i == l && ch[i] == '1')) { int pos = l + 1; for (int j = i + 1; j <= l; j ++ ) { if (ch[j] == '1') { pos = j; break; } } if (pos == l + 1) res += a; else res += min(a, (pos - i - 1) * b); i = pos - 1; } } printf("%d\n", res); } return 0; }