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; }