输入样例
7
BBFBFBB
B为牛的头向后,F为牛的头向前。现在买一台机子可以把连续k头牛转头,问最小转的次数和最小应该买的机子的k。
必须严格k头转,k=3时候,不会出现只转最后一头或最后3头。
可以显然得出从第i头牛反转0次的结果与反转2次是相同的,反转1次与反转3次是相同的。那么从第i头牛开始反转的次数要么为0要么为1。
然后反转的顺序对最终结果是不影响的,那么可以从最左边开始推。
第一头牛如果为B,则其必定反转,第一头牛如果为F,则其必定不反转,然后根据上面的性质,对第二头牛有影响的操作只有反转/不反转从i=2开始的反转,
以此类推可以得到
for(i=0;i+k<=l1;i++){
if(s2[i]=='B'){
t1++;
for(j=i;j<i+k;j++){
if(s2[j]=='B')s2[j]='F';
else s2[j]='B';
}
}
}
但是这么做为O(N^3)显然超时,从左扫到右时,对第i头牛反转的次数为第i-k+1到i-1的反转次数和,那么可以用尺取的办法加之前k-1头牛的反转次数来判断这头牛是否该反转,
这样就可以做到对每个k只需要线性扫描就可以得知其开头的这次反转是否需要。
wa-1 没考虑必须每次严格反转k次
wa-2 没考虑到第i(i<k)头牛的时候虽然是B但是其前面放反转过一次就不需要再进行反转了。我之前的判断是遇到B都反转
wa-3 我在下面的else if 才进行if(i+k>l1){break;}, 这是错误的,有可能i在小于k的时候就不能严格反转k个了。
important points:1、尺取用在与区间相关的地方,其像个尺子一样记录连续k个值。
#include <queue>
#include<iostream>
#include<stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <ctime>
using namespace std;
struct ttt{
double x1,y1,x2,y2;
};
ttt qq[105];
char s1[10500];
int f[5050];
int f2[5050];
int main(){
// freopen("in.txt","r",stdin);
//freopen("output.txt","w",stdout);
int i,j,k,l,f1,f3,t1,t2,t3,m;
int l1,l2,l3,f4,f5;
int n,sum1;
int tt=0;
cin >> l1;
for(i=0;i<l1;i++){
scanf("%c",&s1[i]);
if(s1[i]=='\n'||s1[i]=='\0'){
i--;continue;
}
}
int min1=1e9;
for(k=1;k<=l1;k++){
t1=0;
memset(f,0,sizeof(f));
t2=0;
t3=0;
for(i=0;i<l1;i++){
f2[i]=0; //Ϊ0±íʾûÓз´×ª
if(i+k>l1){
break;
}
if(i<k-1){
if(s1[i]=='B'&&t1%2==0){
f[i]=1;t2++;
f2[i]=1;
}else if(s1[i]=='F'&&t1%2==1){
f[i]=1;t2++;
f2[i]=t1+1;
}else{
f2[i]=t1;
}
t1+=f[i];
}else{
if(t1%2==0&&s1[i]=='B'){
f[i]=1;t2++;f2[i]=t1+1; //û·´×ªÇÒÓ¦¸Ã·´×ª¡£
}else if(t1%2==1&&s1[i]=='F'){ //²»¸Ã·´×ªÈ´·´×ªÁË
f[i]=1;t2++;f2[i]=t1+1;
}else{
f2[i]=t1;
}
t1+=f[i];
t1-=f[i-k+1];
}
// cout << f2[i] << " "<< " " << t1<<endl;
if((f2[i]%2==0&&s1[i]=='B')||(f2[i]%2==1&&s1[i]=='F')){
t3=1; //û·´×ª/²»¸Ã·´×ª
}
// cout << k << " ÔÚ " <<i << " µØ·½" << t3 << endl;
}
for(j=i;j<l1;j++){
f2[j]=t1;
t1-=f[j-k+1];
if((f2[j]%2==0&&s1[j]=='B')||(f2[j]%2==1&&s1[j]=='F')){
t3=1; //û·´×ª/²»¸Ã·´×ª
}
// cout << k << " ÔÚ " <<j << " µØ·½" << t3 << endl;
}
if(t3==0&&t2<min1){
// cout << k << "ÊÇÕýÈ·µÄ" << endl;
min1=t2;
f5=k;
}
}
cout << f5 << " "<< min1 <<endl;
return 0;
}