欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Face The Right Way POJ - 3276 (开关问题)

程序员文章站 2022-05-23 19:46:11
Face The Right Way Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6707 Accepted: 3123 Description Farmer John has arranged his N (1 ≤ N ≤ ......
face the right way
time limit: 2000ms   memory limit: 65536k
total submissions: 6707   accepted: 3123

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头牛反转(超前变朝后,朝后变朝前),需要反转m次,求最少的操作次数m和对应的最小值k
思路:显然,一头牛如果反转两次就等于没有反转,所以一头牛要是被反转两次就多余了。一排牛,我们从左往右看的话,如果第一头牛是头朝后的,那么势必这头牛需要被反转,如果这头牛是头朝前的,那么我们就可以从第二头牛开始进行反转如果第二头牛它是头朝后的话,比如如果一排牛是bbfbfbb(f向前,b向后),那么我们从左往右看第一头牛它是朝后的,所以需要反转,我们假设此时的k是3,那么反转后是ffbbfbb,由于我们是为了第一头牛朝前,那么反转一次后第一头牛肯定朝前了,接下去我们发现第二头牛头刚好也是朝前,那么我们就继续往下看第三头,第三头头往后,那么就反转345号牛,结果为ffffbbb,此时,我们去找第四头牛时发现他也是朝前的,那就继续往下,第五头牛朝后,那么就把567给反转。但最后一次反转后要记得验证是否最后一次使得接下去的k个牛都是头朝前的。而k的找寻这里用了暴力,1-n循环了一遍。
 
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define eps 1e-10
typedef long long ll;
const int maxn = 5e3+3;
const int mod = 1e9 + 7;
int gcd(int a, int b) {
    if (b == 0) return a;  return gcd(b, a % b);
}

int n,m;
int dir[maxn],f[maxn];      //牛的方向 f:0    b:1

int calc(int k)
{
    memset(f,0,sizeof(f));
    int res=0,sum=0;
    for(int i=0;i+k<=n;i++)
    {
        if((dir[i]+sum)%2!=0)
        {
            res++;
            f[i]=1;
        }
        sum+=f[i];
        if(i-k+1>=0)
            sum-=f[i-k+1];
    }
    for(int i=n-k+1;i<n;i++)    //检查剩下的牛是否有面朝后方的情况
    {
        if((dir[i]+sum)%2!=0)
            return -1;
        if(i-k+1>=0)
            sum-=f[i-k+1];
    }
    return res;
}

void solve()
{
    int k=1;
    int m=n;
    for(int k=1;k<=n;k++)
    {
        int m=calc(k);
        if(m>=0 && m>m)
        {
            m=m;
            k=k;
        }
    }
    cout<<k<<" "<<m<<endl;
}
int main()
{
    scanf("%d",&n);
    int num=0;
    for(int i=0;i<n;i++){
        char ch;
        cin>>ch;
        if(ch=='b')
            dir[num]=1;
        else
            dir[num]=0;
       // cout<<dir[num]<<" ";
        num++;
    }
    solve();
    return 0;
}