[IOI2007]Miners

Posted skylee03

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[IOI2007]Miners相关的知识,希望对你有一定的参考价值。

[IOI2007]Miners

题目大意:

两个人吃东西,总共有(3)种食物,每个人每次吃到食物时可以获得的收益是当前食物和前两次吃的食物中,不同食物的种数。现在给定一个长度为(n(nle10^5))的食物序列,按顺序每次将这些食物分配给两个人中的一个。问收益总和的最大值。

思路:

(f[i][j][k][l][m])表示分完前(i)个吃的,(A)最后两个吃了(i)(j)(B)最后两个吃了(l)(m)时的最大收益。

时间复杂度(mathcal O(4^4n))

为了防止MLE需要使用滚动数组。

源代码:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
inline int getfood() {
    register char ch;
    while(!isalpha(ch=getchar()));
    if(ch=='M') return 1;
    if(ch=='F') return 2;
    if(ch=='B') return 3;
    return 0;
}
const int N=1e5+1;
int f[2][4][4][4][4];
inline void up(int &x,const int &y) {
    x=std::max(x,y);
}
inline int calc(int x,int y,const int &z) {
    x=x?:z;
    y=y?:z;
    if(x==y&&y==z) return 1;
    if(x==y&&y!=z) return 2;
    if(x==z&&z!=y) return 2;
    if(y==z&&x!=y) return 2;
    return 3;
}
int main() {
    const int n=getint();
    for(register int j=0;j<4;j++) {
        for(register int k=0;k<4;k++) {
            for(register int l=0;l<4;l++) {
                for(register int m=0;m<4;m++) {
                    f[0][j][k][l][m]=INT_MIN;
                }
            }
        }
    }
    f[0][0][0][0][0]=0;
    for(register int i=1;i<=n;i++) {
        const bool cur=i&1;
        const int x=getfood();
        for(register int j=0;j<4;j++) {
            for(register int k=0;k<4;k++) {
                for(register int l=0;l<4;l++) {
                    for(register int m=0;m<4;m++) {
                        f[cur][j][k][l][m]=INT_MIN;
                    }
                }
            }
        }
        for(register int j=0;j<4;j++) {
            for(register int k=0;k<4;k++) {
                for(register int l=0;l<4;l++) {
                    for(register int m=0;m<4;m++) {
                        if(f[cur^1][j][k][l][m]==INT_MIN) continue;
                        up(f[cur][k][x][l][m],f[cur^1][j][k][l][m]+calc(j,k,x));
                        up(f[cur][j][k][m][x],f[cur^1][j][k][l][m]+calc(l,m,x));
                    }
                }
            }
        }
    }
    int ans=0;
    for(register int j=0;j<4;j++) {
        for(register int k=0;k<4;k++) {
            for(register int l=0;l<4;l++) {
                for(register int m=0;m<4;m++) {
                    up(ans,f[n&1][j][k][l][m]);
                }
            }
        }
    }
    printf("%d
",ans);
    return 0;
}

以上是关于[IOI2007]Miners的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1806[Ioi2007]Miners 矿工配餐 DP

bzoj 1806 [Ioi2007]Miners 矿工配餐(DP)

矿工配餐_IOI2007Miners

BZOJ1806: [Ioi2007]Miners 矿工配餐

bzoj1806[Ioi2007]Miners 矿工配餐 dp

Miners