Face The Right Way
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 2665 | Accepted: 1233 |
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)
算法分析:
大概题意就是有n头牛,在一条直线上,有着不同的方向,前和后,现在让你寻找一个k值,使得每次都只能反转k头牛,求解最少次数与最小k。
当第一次看这个问题时,觉得还是有点棘手的,因为想改变一头牛的方向就必定影响k头牛,但在思考一下,当一头牛被反转2的倍数次时,与初始方向相同,可视为无反转,因为要枚举k并进行N-K+1(最坏情况)次反转,且每次翻转要不断改变dir(方向数组)数组的值,所以复杂度O(N^3),超时,但对于反转改变数值我们可以考虑用一个新的数组f[i]来解决。借助f[i](0或1)来存储每一个位置的反转情况,进而使得复杂度降低为O(N^2)基于此代码如下:
#include<iostream> using namespace std; #define MAXN 5000 int dir[MAXN]; //牛的方向,0 F 1 B int f[MAXN]; //记录每个位置是否发生反转,奇数反转,偶数可视为没发生反转 int N; int calc(int k) { int i,sum=0,res=0; //用sum记录i前面发生的对"当前"f[i]有影响的反转次数,res记录总的反转次数 memset(f,0,sizeof(f)); for(i=0;i+k<=N;i++) //注意结束条件i>n-k,即i=n-k+1 { if((dir[i]+sum)%2!=0) { res++; f[i]=1; } sum+=f[i]; //sum的值来自于记录被反转的次数,若当前i超出k范围, //那么i+1-k及其前面位置发生的反转将不能影响当前i的反转次数,所以减去 if(i+1>=k) sum-=f[i+1-k]; } for(i=N-k+1;i<N;i++) { if((dir[i]+sum)%2!=0) return -1; if(i+1>=k) sum-=f[i+1-k]; } return res; } void solve() { int p,q,ans=N+1; for(int i=1;i<=N;i++) { p=calc(i); if(p!=-1) { ans=(ans<p?ans:p); q=i; } } cout<<q<<" "<<ans<<endl; } int main() { cin>>N; char c; int i; for(i=0;i<N;i++) { cin>>c; dir[i]=(c=='F'?0:1); getchar(); } solve(); return 0; }