题目大意
n头牛排成一行,有的牛面朝前,有的牛面朝后,每一次操作可以使连续的K头牛改变方向;求一个K,使得操作次数最少。输出K以及最少的操作次数。当有多个K满足条件时,输出最小的K。
题目分析
对一个区间来说,多次进行反转操作是没有意义的;另外反转的顺序对结果是没有影响的。所以这道题只需要对所有的可操作区间(即长度为K的区间)考虑是否需要反转。
考虑最左边的牛,当它面朝前时无需反转,当它面朝后时,就反转[1, K]区间一次。然后继续考虑第二头牛即可。
反转的时候不必每头牛都操作一次,只需用一个turns来记录当前区间的反转次数,考虑的下一头牛的状态就由它本身状态+turns的值来决定。随着区间往右移动,我们用区间左右更改的地方来更新turns即可。复杂度为O(n ^ 2)
source code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <cstdio> #include <cstring> const int maxn = 5500; const int INF = 100243535; int a[maxn], f[maxn], cnt[maxn]; int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { char s[10]; scanf("%s", s); a[i] = (s[0] == 'F' ? 0 : 1); } for (int k = 1; k <= n; k++) { memset(f, 0, sizeof(f)); int turns = 0; for (int i = 0; i < n; i++) { if ((a[i] + turns) % 2 == 1) { if (i + k > n) { cnt[k] = INF; break; } f[i] = 1; cnt[k]++; turns++; } if (i - k + 1 >= 0) turns -= f[i - k + 1]; } } int ansK = 1;
for (int k = 2; k <= n; k++) if (cnt[k] < cnt[ansK]) ansK = k; printf("%d %d\n", ansK, cnt[ansK]);
}
|
Last updated: