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\n",K,M); } return 0; }