poj 3276 Face the right way

题目大意:
给定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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值