题意:有N头牛,最初它们的朝向不一致,为使得它们都朝向前方,现有一台转向器,设定K值(一次性翻转相邻的k头牛),问
需要的最小转向次数M和最小的K。
思路:对翻转长度K进行枚举,计算出每次长度k所对应的M。这里,M的计算方法用到尺取遍历查找。从开始遍历查找,当遇到头朝后的牛一定进行反转。
#include<stdio.h>
#include<iostream>
#include <map>
#include<set>
#define inf 0x3f3f3f3f
using namespace std;
set<int>myset;
map<int,int>mymap;
int n,a[5010],m,k,lm;
int f[5010];区间[i,i+k-1]是否反转
char ch;
int judge(int len){//当反转长度为len时,计算反转次数
memset(f, 0, sizeof(f));
int num=0,sum=0;
int i;
for(i=0;i+len<=n;i++){ //尺取法
if((a[i]+sum)%2){ //注意这里判断第i位是否反转的思想 用sum记录反转次数 a[i]+sum为偶数表明牛朝前 反之牛朝后,需要进行反转
num++;
f[i]=1;
}
sum+=f[i];
if(i-len+1>=0) sum-=f[i-len+1];//移动尺子
}
for(i=n-len+1;i<n;i++){ //对剩下的n-(n/len)头牛
if((a[i]+sum)%2)
return -1;//如果有朝向后方的就返回-1,说明此时的k不能将所有的牛都朝向前方
if(i-len+1>=0) sum-=f[i-len+1];
}
return num;
}
void solve(){
int i;
lm=n;
k=1;
for(i=1;i<=n;i++){// 枚举k
m=judge(i);
if(m>=0&&lm>m){
lm=m;
k=i;
}
}
printf("%d %d",k,lm);
}
int main(){
int i;
scanf("%d",&n);
getchar();
for (i=0; i<n; i++) {
scanf("%c",&ch);
getchar();
if(ch=='B') a[i]=1;
else a[i]=0;
}
solve();
return 0;
}