• P2837 晚餐队列安排


    P2837 晚餐队列安排

    我们先来理解一下题意:

       奶牛保持一个混乱的顺序站好不动,手里拿着的牌只有可能是1号或 2 号,农场主很懒 要改它们的牌改成以下三种:

         111111111(全是第一批)

         22222222(全是第二批)

         111112222(前边是第一批,后边是第二批)

         注意不可以是22222111111,因为1,2代表了吃饭的批次,第一批,第二批  

         本蒟蒻一开始曲解题意以为相同数字排在一起就好了

    SO

    我们设 f [ i ] [ 1 ] 为奶牛 i 号要把自己改成 1 时农场主需要改的最少号码数

                f [ i ] [ 2 ] 为奶牛 i 号要把自己改成 2 时农场主需要改的最少号码数

                (已经改到了第 i 头奶牛)

    如果此时奶牛 i 是1,那么它分两种情况讨论:

              (1)把自己改成1 它本来就是 

                       所以它就不用改了,此时农场主需要改的号码数就由 i -1奶牛决定

                       i 奶牛已经是1了,所以为了前方保持一致,倒推 i - 1奶牛也是 1

                       转移方程为:f [ i ] [ 1 ] = f [ i - 1 ] [ 1 ] ; 

              (2)把自己改成2

                       农场主一定要改它,所以一定要+1

                       那么第  i - 1 只奶牛可能改为 1 或 2 ,所以要取最小值

                       转移方程为:f [ i ] [ 2 ] = min ( f [ i - 1 ] [ 2 ] , f [ i - 1 ] [ 1 ] ) + 1 ;

    如果此时奶牛 i 是2,依次类推;

    那么

    最后比较 f [ n ] [ 1 ] , f [ n ] [ 2 ] ,即把最后一只牛改成1 还是2 所需改的次数最少即可

    DP代码

    #include<iostream>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm>
    using namespace std;
    int n,a[30001],f[30001][3],ans;
    int main()
    {    
        scanf("%d",&n);
        
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
    
        for(int i=1;i<=n;i++)
        {
            if(a[i]==1)
            {
                f[i][1]=f[i-1][1];
                f[i][2]=min(f[i-1][2],f[i-1][1])+1;
            }
            else
            {
                f[i][1]=f[i-1][1]+1;
                f[i][2]=min(f[i-1][2],f[i-1][1]);
            }
        }
        
        ans=min(f[n][1],f[n][2]);
    
        printf("%d",ans);
      
        return 0;
    }
  • 相关阅读:
    [转]创建节约内存的JavaBean
    TCP协议
    redis常用命令
    Windows&Linux常用命令笔记
    二叉树学习笔记
    云计算入门
    redis主从切换
    spring 异步处理request
    ibatis工作原理
    工作了3年的JAVA程序员应该具备什么技能?(转)
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10606264.html
Copyright © 2020-2023  润新知