题目大意:
给定n头牛,F表示方向朝前,B表示方向向后,问怎么翻转恰好k个长度的区间,使得翻转次数最少的让牛都超前。
思路:
最差情况n^3的暴力。果断TLE啊。。。
那怎么优化。
在n^3循环中,我们循环了许多 遍中间的值。。
那怎么去掉他们?
我们可以统计他们的关系,也就是和钱一头牛一不一样,给一个原点牛,他的方向是向前的。
如果f[i]=1,那么就需要翻转他和他后面的区间,但是翻转区间之内的东西跟前一个的关系还是没有变的。所以只用修改f[i]和f[i+k]就ok
判断一下是否都向前就ok了!
这种题其实是一种依赖关系。因为他可以只用跟前一头牛的关系是怎样的来判断整个是否一样。相当于一种跳区间吧?
类似开关灯问题?
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//by mars_ch
int n;
int f[5005],b[5005];
//0是相同,1是不同
void init()
{
for(int i=1;i<=n;i++)
{
b[i]=f[i];
}
}
bool check()
{
for(int i=1;i<=n;i++)
{
if(b[i]) return false;
}
return true;
}
int main()
{
char a='F';
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
char c;
scanf("\n%c",&c);
if(c == a) f[i]=0;
else f[i]=1;
a=c;
}
int cnt=0,ans=0x3fffffff,res=0;
for(int i=1;i<=n;i++) //枚举范准区间k
{
init();
cnt=0;
for(int j=1;j<=n;j++) //寻找
{
if(j+i>n+1) continue;
if(b[j])
{
cnt++;
b[j]=0,b[i+j]^=1;
}
}
if(!check()) continue;
if(cnt<ans)
{
ans=cnt;
res=i;
}
}
printf("%d %d\n",res,ans);
return 0;
}