Face The Right Way
题目链接: POJ - 3276题意:现有一排奶牛, 有的头朝前, 有的头朝后, 要求每次翻转k个连续奶牛, 操作m次后奶牛全部头朝前, 求出m最小时, k最小值;
首先k一定是由1~n, 然后对于每个k求一个m, 开始我的思路是每翻转一个奶牛对他后边k-1个奶牛改变状态, 就是n^3的复杂度, 果断TE;
然后果断搜了题解;
当我们对i操作时, 只影响i~i+k-1的区间, 当到j时, 只要知道前边的操作有几个对j有影响, 就可以判断出j此时的状态了;
维护一个sum, 表示i前边有几个操作会对i有影响;怎么维护是个问题………
仔细想一想i操作后对后边k-1个有影响, 但是当j和i距离超过k-1后i就不会影响到j, 此时sum就可以减去i处的操作;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int n;
int cow[5100], t[5100];
int cnt(int k){
memset(t, 0, sizeof(t));
int res=0, sum=0;
for(int i=0; i+k<=n; i++){
if((cow[i]+sum)%2){
res++;
t[i]=1;
}
sum+=t[i];
if(i-k+1>=0) sum-=t[i-k+1];
}
for(int i=n-k+1; i<=n; i++){
if((cow[i]+sum)%2) return INF;
if(i-k+1>=0) sum-=t[i-k+1];
}
return res;
}
void solve(){
int ans_k=0, ans_m=INF;
for(int k=1; k<=n; k++){
int tmp=cnt(k);
if(tmp<ans_m){
ans_m=tmp;
ans_k=k;
}
}
printf("%d %d\n", ans_k, ans_m);
}
int main(){
scanf("%d", &n);
char s[5];
for(int i=0; i<n; i++){
scanf("%s", s);
if(s[0]=='F') cow[i]=0;
else cow[i]=1;
}
solve();
return 0;
}