• 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;
    }
  • 相关阅读:
    芯片产品介绍
    稀疏矩阵理论与实践
    EUV极紫外光刻技术
    国内AI与芯片企业列表
    中国软件外包现状对比
    GPU指令集技术分析
    寒武纪智能系统参数
    TVM量化路线图roadmap
    EUV光刻机市场与技术
    轻松部署 .NET 5 应用程序,这个指南一定不要错过
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/7725417.html
Copyright © 2020-2023  润新知