zoukankan      html  css  js  c++  java
  • USACO35 翻转奶牛(尺取法)

    通过这道题了解了不少有关翻转的知识呢......

    首先,我们枚举翻转的区间长度k,假设i有个按钮,按下就可以让i~i+k-1翻转,那就有两个状态,按i或不按i(因为按两次相当于没按),那就往后扫一遍,假如要翻转就翻转,不用就不翻,但是这样就会有个问题,每次翻转都要把后面的k个置反,能不能优化?

    可以,这就是尺取法。我们用sum表示当前区间翻转了多少次,假如第一头奶牛被翻转,而第二头奶牛也需要(1表示需要,0表示不须),而当前k=2,那就sum=1,我们用(sum+1)%2,假如等于0,就不用翻第二头奶牛了。那尺取体现在那呢,就是我们枚举的区间,前面的区间,假如不能对我当前的点造成影响了,就是i-k的位置,翻不翻转,都对当前位置没有影响,他的影响范围只有i-k~i-1,所以这时sum减去他的影响。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int n;
    int f[5100],c[5100];
    int solve(int k)
    {
        int cnt=0,sum=0;
        memset(f,0,sizeof(f));
        for(int i=1;i<=n-k+1;i++)
        {
            if((c[i]+sum)%2==1)
            {
                cnt++;
                f[i]=1;
            }
            sum+=f[i];
            if(i-k+1>=1)sum-=f[i-k+1];
        }
        for(int i=n-k+2;i<=n;i++)
        {
            if((c[i]+sum)%2==1)return 2147483647;
            if(i-k+1>=1)sum-=f[i-k+1];
        }
        return cnt;
    }
    char ss[10];
    int main()
    {
        scanf("%d",&n);
        int ansk=1,ansm=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ss+1);
            if(ss[1]=='F') c[i]=0;
            if(ss[1]=='B'){c[i]=1;ansm++;}
        }
        for(int k=2;k<=n;k++)
        {
            int m=solve(k);
            if(m<ansm)ansk=k, ansm=m;
        }
        printf("%d %d
    ",ansk,ansm);
        return 0;
    }
  • 相关阅读:
    ubuntu 安装 redis desktop manager
    ubuntu 升级内核
    Ubuntu 内核升级,导致无法正常启动
    spring mvc 上传文件,但是接收到文件后发现文件变大,且文件打不开(multipartfile)
    angular5 open modal
    POJ 1426 Find the Multiple(二维DP)
    POJ 3093 Margritas
    POJ 3260 The Fewest Coins
    POJ 1837 Balance(二维DP)
    POJ 1337 A Lazy Worker
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/7725417.html
Copyright © 2011-2022 走看看