poj 3276 Face The Right Way

题意:有N头顺序排列的牛,有的头朝前,有的朝后,现在有一台机器,可以设置每次翻转连续的k头牛,求最小的的翻转次数m

分析:一头牛翻转两次=不翻转,也就是说一头牛要么翻转,要么不翻转,那么枚举k,然后模拟求翻转的次数,这样的话,O(n^3),超时,根据尺取法的思想,我们依次观察每头牛是否翻转,f[i]表示i是否翻转

那么对于j来说,(j-k+1)~(j-1) 的f的和就是j在前面被翻转的次数,sum+dir[j]为偶,不翻转,否则,翻转,对于出了框子的牛,sum-f[i-k+1],

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5005;
int dir[maxn],f[maxn],n;

int solve(int k){
    memset(f,0,sizeof(f));
    int sum=0,ans=0;
    for(int i=0;i+k<=n;i++){
        if((sum+dir[i])%2!=0){
            ans++;
            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((sum+dir[i])%2!=0)
        return -1;
      if(i-k+1>=0)
        sum-=f[i-k+1];
    }
    return ans;
}

int main(){
    while(~scanf("%d",&n)){
        getchar();
        char c;
        for(int i=0;i<n;i++){
            c=getchar();getchar();
            if(c=='B')
              dir[i]=1;
            else
              dir[i]=0;
        }
        int K=1,M=n;
        for(int k=1;k<=n;k++){
            int m=solve(k);
            if(m>=0&&M>m){
                M=m;
                K=k;
            }
        }
        printf("%d %d
",K,M);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jihe/p/5571944.html