矿工配餐

题目大意
有两个矿井及N辆矿车,每个矿工的产煤量与其最后三顿饭的种类数有关。求最大产煤量。

算法
DP,f[i][j1][j2][j3][j4][j5]表示处理到第i辆,第一个矿井前两天吃的是j1,j2,第二个矿井前两天吃的是j3,j4。

但是空间只有18MB,所以我们采用滚动数组

代码

#include <cstdio>
#include <memory.h>
#include <algorithm>
using namespace std;
#define max(a,b) ((a)>(b))?(a):(b)
#define min(a,b) ((a)<(b))?(a):(b)
#define _f(i,a,b) for(int i=a;i<=b;i++)
unsigned char f[100001]={0};
int x[4][4][4][4],y[4][4][4][4];
int main(){
    int n;
    scanf("%d\n",&n);
    for(int i=1;i<=n;i++){
        char ch=getchar();
        switch(ch){
            case 'M':
                f[i]++;
            case 'F':
                f[i]++;
            case 'B':
                f[i]++;
        }
    }
    memset(x,0,sizeof(x));
    for(int i=n;i>=1;i--){
        memset(y,0,sizeof(y));
        _f(j1,0,3)_f(j2,0,3)_f(j3,0,3)_f(j4,0,3){
            if((j1 && !j2)||(j3 && !j4))
                continue;
            int _1,_2;
            if((!j1 && !j2)||(!j1 && j2==f[i])||
                (j1==j2 && j2==f[i]))
                _1=1;
            else if(j1!=j2 && j2!=f[i] && j1!=f[i] && j1 && j2)
                _1=3;
            else
                _1=2;
            if((!j3 && !j4)||(!j3 && j4==f[i])||
                (j3==j4 && j4==f[i]))
                _2=1;
            else if(j3!=j4 && j4!=f[i] && j3!=f[i] && j3 && j4)
                _2=3;
            else
                _2=2;
            y[j1][j2][j3][j4]=max(x[j2][f[i]][j3][j4]+_1,
                x[j1][j2][j4][f[i]]+_2);
        }
        swap(x,y);
    }
    printf("%d\n",x[0][0][0][0]);
    return 0;
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务