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: NLines 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 BSample Output
3 3Hint 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头)头奶牛一次性翻转朝向(n>=k>=1),问你最少的翻转次数和此时对应的k值。 思路: 首先可以依次枚举区间长度len,在不同的区间长度的情况下,查看这样的长度是否能使奶牛全部朝前,并记录总翻转次数,取最小。 进而在每种区间长度len的讨论中分析如下: 对于目前的奶牛,我们的决策就两种,翻或不翻,这要看他在目前朝前还是朝后(对于判断这个我们可以去分析他本身的朝向和已翻过的次数,翻过奇数次则与初始相反,翻过偶数次相当于没翻,与初始相同),而且将一个区间的点翻转时不会影响到区间起点前面的点(无后效性),同时要记录总翻转次数。 决策在循环中,但这个循环结束并不一定所有的奶牛都能朝前,因为我们只能处理到距离最后一个奶牛len-1位置的奶牛(要翻转就只能翻转一个区间),所以如果循环结束但在最后几个未处理到的奶牛中有朝后的,则这个len不能使所有奶牛朝前(当然len=1时是一定可以的),进行下一个len(=len+1)的讨论。 对于每种区间长度讨论出来的总翻转次数(如果最后都能朝前的话),取最小值。 最终输出最小值以及它对应的区间长度len。 嗯。。。。。大体上就是这样 接下来是在每个决策中判断这个牛目前朝向时,如何查看记录过的这个牛翻过的次数。 我们可以定义一个变量去记录当前处理的点的反转次数,如果他脱离一个区间,就减去他所脱离这个区间起点翻转的次数,这样这个变量就可以存储目前点翻转的次数了。 代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=5e3+3; 7 int n; 8 char fac; 9 bool face[maxn],f[maxn];//face: 0->qian 1->hou f:0->don't need turn ,1->need 10 int Fan(int len){ 11 memset(f,0,sizeof(f)); 12 int cishu=0,sum=0;//sum->已经turn的次数 cishu->turn的总次数 13 for(int i=1;i+len-1<=n;++i){ 14 if((face[i]+sum)%2==1){//i朝后 15 cishu++; 16 f[i]=1; 17 } 18 sum+=f[i]; 19 if(i-len+1>=1)sum-=f[i-len+1];//现在 sum 是下一个i已经turn的次数了 20 } 21 //因为最后一个i是离最后一头牛len-1长度,检查未处理过的牛是否朝后,if this,无解 22 for(int i=n-len+1+1;i<=n;++i){ 23 if((face[i]+sum)%2==1)return -1; 24 if(i-len+1>=1)sum-=f[i-len+1]; 25 } 26 return cishu; 27 } 28 void Solve(){ 29 int K=n,cishu=n; 30 for(int len=1;len<=n;++len){//枚举区间长度 31 int m=Fan(len); 32 if(m>=0&&cishu>m){ 33 cishu=m;K=len; 34 } 35 } 36 printf("%d %d\n",K,cishu); 37 return; 38 } 39 int main(){ 40 // freopen("1.in","r",stdin); 41 scanf("%d",&n); 42 for(int i=1;i<=n;++i){ 43 scanf(" %c",&fac); 44 if(fac=='B')face[i]=1; 45 } 46 Solve(); 47 return 0; 48 }