贪心...先枚举k, 然后从左往右扫一遍, 发现位置p的牛的状态不符合就将 [p, p + k ) 的牛都转身, 假如p + k - 1 已经超过了最右边牛的位置那这个k就不符合要求. 符合要求的就可以用来更新answer.这个贪心的正确性是很显然的.前p - 1头牛都已朝前, 再改动它们也做不到更优; 而要让第p头牛转身, 那就只能让[p, p + k )的牛转身.
考虑如何判断位置p的牛的状态, 我们发现p的状态与它本身和[ p - k - 1, p )这个区间内的牛的转身次数有关, 因为转身两次相当于没转, 用异或进行操作可以做到O(1). 枚举O(n), 扫描O(n), 总时间复杂度为O(n²)
-------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rep(i, n) for(int i = 0; i < n; i++)
#define clr(x, c) memset(x, c, sizeof(x))
using namespace std;
const int maxn = 5009;
const int inf = 1000000000;
int A[maxn], n, H[maxn];
int main() {
freopen("test.in", "r", stdin);
cin >> n;
rep(i, n) {
char c;
scanf(" %c", &c);
A[i] = c == ‘F‘ ? 0 : 1;
}
int ans[2] = {0, inf};// {k, m}
for(int i = 1; i <= n; i++) {
clr(H, 0);
int cnt = 0, p = 0;
rep(j, n) {
if(j >= i) p ^= H[j - i];
if(i + j > n) {
if(A[j] ^ p) cnt = inf;
continue;
}
if(A[j] ^ p)
cnt++, H[j] ^= 1;
p ^= H[j];
}
if(ans[1] > cnt)
ans[0] = i, ans[1] = cnt;
}
cout << *ans << ‘ ‘ << ans[1] << "\n";
return 0;
}
-------------------------------------------------------------------
1704: [Usaco2007 Mar]Face The Right Way 自动转身机
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 313 Solved: 183
[Submit][Status][Discuss]
Description
农夫约翰有N(1≤N≤5000)只牛站成一排,有一些很乖的牛朝前站着.但是有些不乖的牛却朝后站着.农夫约翰需要让所有的牛都朝前站着.幸运的是约翰最近买了一个自动转身机.这个神奇的机器能使K(1≤K≤N)只连续的牛转身. 因为约翰从来都不改变K的价值,请帮助他求出K,使旋转次数M达到最小.同时要求出对应的M.
Input
第1行:整数N.
第2行到第N+1行:第i+l行表示牛j的朝向,F表示朝前,B表示朝后.
Output
一行两个数,分别是K和M,中间用空格隔开
Sample Input
7
B
B
F
B
F
B
B
INPUT DETAILS:
There are seven cows and they are facing backward, backward, forward,
backward, forward, backward, and backward, respectively.
Sample Output
3 3
OUTPUT DETAILS:
For K = 3, the machine must be operated three times: turn cows (1,2,3),
(3,4,5), and finally (5,6,7):
B > F F F
B > F F F
F > B > F F
B B > F F
F F > B > F
B B B > F
B B B > F
HINT
当K=3时神奇的机器旋转3次:(1,2,3),(3,4,5),和(5,6,7)