ps:改了这么久,对拍一下就找到错误了。贪心,首部出现的1,是不用去剪的,所以当作特殊元素考虑,因此当 k == 0的时候 或者 k没有用完的时候一定要考虑是否用到了首部那一节(cntSt)。而尾部只需要剪一次,中间的部分需要减两次,贪心的时候要分别讨论(有史以来写得最丑的代码!!!)
inline bool cmp(P a, P b) { return a.first > b.first; } int main() { while (scanf("%d %d", &n, &k) != EOF) { scanf("%s", s); int cntSt = 0, cntEd = 0, st = 0, ed = n - 1; for (int i = 0; i < n; ++i) { if (s[i] != '1') { st = i; break; } else cntSt++; } for (int i = n - 1; ~i; --i) { if (s[i] != '1') { ed = i; break; } else cntEd++; } if (cntEd == n) { cout << n << endl; continue; } vector<int> ans; ans.clear(); mem(use, 0); P p[N]; int t = 0; for (int i = st; i <= ed; ++i) { if (s[i] == '1') t++; else { if (t) ans.pb(t); t = 0; } } if (t) ans.pb(t); if (k == 0) { cout << cntSt << endl; continue; } if (k == 1) { int res = cntEd + cntSt; for (int i = 0; i < ans.size(); ++i) upd(res, ans[i]); cout << res << endl; continue; } for (int i = 0; i < ans.size(); ++i) p[i].first = ans[i], p[i].second = 0; if (cntEd) p[ans.size()].first = cntEd, p[ans.size()].second = 1; sort(p, p + ans.size() + 1, cmp); int res = 0; for (int i = 0; i < ans.size() + 1; ++i) { if (!k) break; if (p[i].second == 1) { res += p[i].first; k--; use[cntEd] = 1; if (k == 0) res += cntSt; } else { if (k > 2) { res += p[i].first; k -= 2; } else if (k == 2) { if (use[cntEd]) res += p[i].first + cntSt; else res += max(p[i].first + cntSt, p[i].first + cntEd); k -= 2; } else if (k == 1) { if (use[cntEd]) res += max(cntSt, p[i].first); else res += max(cntSt + cntEd, p[i].first); k--; } } } if (k) res += cntSt; cout << res << endl; } return 0; }