POJ:3276-Face The Right Way(线性反转)
Face The Right Way
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 6259 Accepted: 2898
Description
Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing forward, like good cows. Some of them are facing backward, though, and he needs them all to face forward to make his life perfect.
Fortunately, FJ recently bought an automatic cow turning machine. Since he purchased the discount model, it must be irrevocably preset to turn K (1 ≤ K ≤ N) cows at once, and it can only turn cows that are all standing next to each other in line. Each time the machine is used, it reverses the facing direction of a contiguous group of K cows in the line (one cannot use it on fewer than K cows, e.g., at the either end of the line of cows). Each cow remains in the same location as before, but ends up facing the opposite direction. A cow that starts out facing forward will be turned backward by the machine and vice-versa.
Because FJ must pick a single, never-changing value of K, please help him determine the minimum value of K that minimizes the number of operations required by the machine to make all the cows face forward. Also determine M, the minimum number of machine operations required to get all the cows facing forward using that value of K.
Input
Line 1: A single integer: N
Lines 2..N+1: Line i+1 contains a single character, F or B, indicating whether cow i is facing forward or backward.
Output
Line 1: Two space-separated integers: K and M
Sample Input
7
B
B
F
B
F
B
B
Sample Output
3 3
Hint
For K = 3, the machine must be operated three times: turn cows (1,2,3), (3,4,5), and finally (5,6,7)
解题心得:
- 题意就是给你一列牛,有的牛朝前面有的牛朝后面,你可以选择一段区间,让区间内的牛方向反转,现在你要选择一个区间,要总的反转次数最少让所有的牛都面向前面。
- 最暴力的方法就是递归枚举,大概O(2^n)的复杂度,不现实,然后观察会发现,其实对于反转操作来说顺序是没有意义的,这样如果我们每次考虑最左边的牛,那么每次改变之后左边的牛的方向将不会变化,只有右边的牛的方向会变化。那么可以选择从左边开始,枚举区间长度,每次从最左边向右遍历,将区间里面的牛反转,操作下来复杂度大概是O(n^3)。但是想一下,一个牛两次反转之后就等于没有变化,这样我们只需要知道每一头牛翻转了多少次就行了,不必一头一头的操作。这样就可以记录在当前牛之前对这个牛操作了多少次,就可以减去一层的复杂度。这个时候复杂度就变成了O(n^2),可以过了。
#include <algorithm>
#include <stdio.h>
#include <cstring>
#include <climits>
using namespace std;
const int maxn = 5e3 + 10;
int add[maxn],dir[maxn];
void init(int &n) {
scanf("%d", &n);
char s[5];
for (int i = 1; i <= n; i++) {
scanf("%s", s);
if (s[0] == 'B')
dir[i] = 1;
}
}
void solve(int n) {
int sum,cnt,Min = INT_MAX,len;
for (int k = 1; k <= n; k++) {
memset(add,0,sizeof(add));
cnt = sum = 0;
for (int i = 1; i <= n - k + 1; i++) {
if ((sum + dir[i]) % 2 == 1) {
add[i] = 1;
cnt++;
}
sum += add[i];
if (i - k + 1 >= 1)
sum -= add[i-k+1];
}
bool flag = false;
for(int i=n-k+2;i<=n;i++) {//检验剩下的k-1头牛是否符合向前
if((sum+dir[i])%2 == 1) {
flag = true;
break;
}
if(i-k+1 >= 1)
sum -= add[i-k+1];
}
if(flag)
continue;
if(cnt < Min) {
Min = cnt ;
len = k;
}
}
printf("%d %d\n",len,Min);
}
int main() {
int n;
init(n);
solve(n);
}