您的位置:首页 > 其它

POJ 3276 Face The Right Way 反转

2016-10-31 22:00 375 查看
大致题意:有n头牛,有些牛朝正面,有些牛朝背面。现在你能一次性反转k头牛(区间[i,i+k-1]),求使所有的牛都朝前的最小的反转次数,以及此时最小的k值。

首先,区间反转的顺序对结果没有影响,并且,同一区间无需进行多次反转。我们首先从最左边的开始,最左边的牛如果朝前,则不需要反转,用f[i]=0记录下来;反之则反转,f[i]=1.如果最左边的朝向为前,整个序列就可以减少1,依次递推下去。

当然,有些k值也可能不能完全反转,比如 1 0 1 ,当k=3时,是不可能反转完成的。

还有既然是区间反转,自然会影响之后的牛是否反转,此时用sum进行记录,判断sum+牛的方向 是否为奇数。

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 5000 + 10;

int n;
char s[maxn];
int dir[maxn];
int f[maxn];     //区间[i, i + k - 1]是否进行反转

int calculate_m(int k)
{
int sum=0;
int ret=0;
memset(f,0,sizeof(f));
for(int i=0;i<=n-k;i++)
{
if((dir[i]+sum)%2)
{
ret++;
f[i]=1;
sum+=f[i];
}
if(i-k+1>=0) // 减去不影响的反转次数
sum-=f[i-k+1];
}
for(int i=n-k+1;i<n;i++) //判断剩余的区间
{
if((dir[i]+sum)%2)
return -1;
if(i-k+1>=0)
sum-=f[i-k+1];
}
return ret;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
getchar();
int c=getchar();
if(c=='F')
dir[i]=0;
else
dir[i]=1;
}
int ans_k=1,ans_m=n;
for(int i=1;i<=n;i++)
{
int m=calculate_m(i);
if(m>=0 && m<ans_m)
{
ans_k=i;
ans_m=m;
}
}
printf("%d %d\n",ans_k,ans_m);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: