Face The Right Way POJ - 3276

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



猜你喜欢

转载自blog.csdn.net/sirius_han/article/details/80230041