P2896 [USACO08FEB]一起吃饭Eating Together

传送门

可以考虑DP

设 f [ i ] [ 1/2/3 ] [ 0/1 ] 表示当前考虑到第 i 头牛,打算让当前位置的编号变成 1/2/3,并且打算让整段序列上升/下降 0/1

然后就对每种情况慢慢考虑转移就行了

可以发现第一维可以直接优化掉,然后空间就是 O(1),时间就是 O(n)

太简单就不用注释了吧...

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
int n,f[4][2];
int main()
{
    int a;
    n=read();
    while(n--)
    {
        a=read();
        if(a==1)
        {
            f[3][0]=min(f[3][0],min(f[2][0],f[1][0]))+1;
            f[2][0]=min(f[2][0],f[1][0])+1;
            f[1][1]=min(f[3][1],min(f[2][1],f[1][1]));
            f[2][1]=min(f[3][1],f[2][1])+1;
            f[3][1]=f[3][1]+1;
            continue;
        }
        if(a==2)
        {
            f[3][0]=min(f[3][0],min(f[2][0],f[1][0]))+1;
            f[2][0]=min(f[2][0],f[1][0]);
            f[1][0]=f[1][0]+1;
            f[1][1]=min(f[3][1],min(f[2][1],f[1][1]))+1;
            f[2][1]=min(f[3][1],f[2][1]);
            f[3][1]=f[3][1]+1;
            continue;
        }
        f[3][0]=min(f[3][0],min(f[2][0],f[1][0]));
        f[2][0]=min(f[2][0],f[1][0])+1;
        f[1][0]=f[1][0]+1;
        f[1][1]=min(f[3][1],min(f[2][1],f[1][1]))+1;
        f[2][1]=min(f[3][1],f[2][1])+1;
    }
    int ans=1e9+7;
    for(int i=1;i<=3;i++) for(int j=0;j<=1;j++) ans=min(ans,f[i][j]);
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-10-28 10:14  LLTYYC  阅读(245)  评论(0编辑  收藏  举报