POJ--3276--Face The Right Way(暴力枚举)

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

题意:有n个奶牛,B表示该牛朝向为右,F表示朝左,K分别表示把一段连续K个奶牛反转朝向,使得最后所有奶牛都朝左,当前K可以得到一个最小操作次数M,问K为何值时M最小,满足M最小的同时 让K也最小,输出K和M。

解析:因为N<=5000,因此我们可以暴力枚举K,对于每个K计算出当前所需最小操作次数,问题就变成了对于给定的K,如何求最小操作次数,其实从左往右遍历,如果当前奶牛朝右,那么该牛肯定需要转向,影响后续k-1个,因此我们可以维护一个sum表示当前位置受到几次反转影响,就可以判断出当前位置是否需要反转,同时如果我们出了某个反转区间,sum应该-1,如此就可以遍历完成计算。

#include 
#include 
using namespace std;
const int N=5e3+5;
typedef long long ll;
char a[N];//读入字符串
int n,w[N],x[N];//w[i]=1表示这个位置初始向右,x[i]表示这个位置是否是反转的左端点
int go(int k)//返回当前k值所需操作次数
{
    int sum=0,cnt=0;//sum表示当前位置受到几次反转
    memset(x,0,sizeof x);//每次独立,需要初始化
    for(int i=1;i+k-1<=n;i++)
    {
        if((sum+w[i])%2)//需要反转
        {
            cnt++;
            x[i]=1;//当前位置往后k个反转
            sum++;
        }
        if(i-k+1>=1) sum-=x[i-k+1];
        //如果x[i-k+1]反转过,因为已经出了这个区间,因此需要减去
    }
    for(int i=n-k+2;i<=n;i++)//判断最后k-1个是否合法
    {
        if((sum+w[i])%2)//表示无解
        {
            cnt=-1;
            break;
        }
        if(i-k+1>=1) sum-=x[i-k+1];
    }
    return cnt;
}
void solve()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf(" %c",&a[i]);
    for(int i=1;i<=n;i++) if(a[i]=='B') w[i]=1;
    int M=n,K;
    for(int k=1;k<=n;k++)
    {
        int res=go(k);
        if(res>=0&&res

你可能感兴趣的:(算法,数据结构,c++,c语言)