正解似乎是 dp, 但是我写了贪心,求 hack。
思想是找到一块向两边拓展着移动。
#include <cstdio>
#include <cmath>
#include <algorithm>
const int N = 5005;
int n, a[N], t, an[N], ans = 0x3f3f3f3f, cnt;
int findNext(int *a, int x) {
while(x <= n && a[x] == 0) x++;
if(x > n) x = -1;
return x;
}
void findBlock(int x, int &l, int &r) {
while(x <= n && a[x] == 0) x++;
l = x;
while(x <= n && a[x] == 1) x++;
r = x-1;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int l, r;
findBlock(0, l, r);
// printf("%d %d\n", l, r);
for( ; l <= n && r <= n; findBlock(r+1, l, r))
for(int j = 1, tot = 0; tot < r-l+1; j++) {
if(l-j+1 >= 1 && a[l-j+1] == 0 && an[l-j+1] == 0) an[l-j+1] = 1, tot ++;
if(tot == r-l+1) break;
if(r+j-1 <= n && a[r+j-1] == 0 && an[r+j-1] == 0) an[r+j-1] = 1, tot ++;
}
// for(int i = 1; i <= n; i++) printf("%d ", an[i]);
int i1 = findNext(an, 1), i2 = findNext(a, 1);
for( ; i1 != -1 && i2 != -1; i1 = findNext(an, i1+1), i2 = findNext(a, i2+1))
t += std::abs(i2 - i1);
printf("%d", t);
return 0;
}