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;
    }
  • 相关阅读:
    TMainMenu 类 手动建立菜单 : 指定快捷键《转》
    确定多重选择列表控件 (List Control) 中的选定内容
    【320K】大峡谷The Music of The Grand Canyon
    35种音乐的分类
    ASP中常用的变量命名规则
    关于DBF文件导入问题
    ASP.NET里的变量命名规则
    ASP中数据库安全问题之我见
    用err.raise自定义错误信息
    关于编程风格的讨论 PioneerMan(原作)
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/7725417.html
Copyright © 2011-2022 走看看