zoukankan      html  css  js  c++  java
  • BZOJ1806 [Ioi2007]Miners 矿工配餐 [动态规划]

    矿工配餐

    题目描述见链接 .


    color{red}{正解部分}

    F[i,a,b,c,d]F[i, a, b, c, d] 表示送完第 ii 次餐车, 第一个矿坑使用的最后两个元素为 a,ba,b, 第二个矿坑使用的最后两个元素为 c,dc,d 所能获得的最优值,

    转移很显然:
    F[i,si,a,c,d]=F[i1,a,b,c,d]+calc(a,b,si)F[i, s_i, a, c, d] = F[i-1, a, b, c, d] + calc(a, b, s_i)
    F[i,a,b,si,c]=F[i1,a,b,c,d]+calc(c,d,si)F[i, a, b, s_i, c] = F[i-1, a, b, c, d] + calc(c, d, s_i)

    时间复杂度 O(N44)O(N*4^4) .


    color{red}{实现部分}

    这道题目卡空间, 需要滚动数组 .

    计算答案的函数需要注意不能这么写, 这么写会使得三个相同的情况返回 00 .

    int calc(int a, int b, int c){
            if(!a && !b) return 1;
            else if(!a) return (b!=c)?2:1;
            return (a!=b) + (a!=c) + (b!=c);
    }
    

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 100005;
    
    int N;
    int t1;
    int t2;
    int Ans;
    int Tong[4];
    int F[2][4][4][4][4];
    
    char S[maxn];
    
    int Trans(char c){ return (c!='M')?(c!='B'?1:2):3; }
    
    int calc(int a, int b, int c){
            int res = 0;
            Tong[1] = Tong[2] = Tong[3] = 0;
            if(a && (++ Tong[a]) == 1) res ++;
            if(b && (++ Tong[b]) == 1) res ++;
            if(c && (++ Tong[c]) == 1) res ++;
            return res;
    }
    
    int main(){
            scanf("%d", &N); scanf("%s", S+1);
            int cur = 0;
            memset(F, -1, sizeof F); F[0][0][0][0][0] = 0;
            for(reg int i = 1; i <= N; i ++){
                    cur ^= 1; memset(F[cur], -1, sizeof F[cur]);
                    for(reg int a = 0; a <= 3; a ++)
                            for(reg int b = 0; b <= 3; b ++)
                                    for(reg int c = 0; c <= 3; c ++)
                                            for(reg int d = 0; d <= 3; d ++){
                                                    if(F[cur^1][a][b][c][d] == -1) continue ;
                                                    int now = Trans(S[i]);
                                                    F[cur][now][a][c][d] = std::max(F[cur][now][a][c][d], F[cur^1][a][b][c][d] + calc(b, a, now));
                                                    F[cur][a][b][now][c] = std::max(F[cur][a][b][now][c], F[cur^1][a][b][c][d] + calc(d, c, now));
                                            }
            } 
            for(reg int a = 0; a <= 3; a ++) 
                    for(reg int b = 0; b <= 3; b ++) 
                            for(reg int c = 0; c <= 3; c ++) 
                                    for(reg int d = 0; d <= 3; d ++) Ans = std::max(Ans, F[cur][a][b][c][d]);
            printf("%d
    ", Ans);
            return 0;
    }
    
  • 相关阅读:
    C语言保留字
    N的阶乘末尾有多少个零?
    控制台初级玩法
    数据结构笔记#二分法查找
    数据结构应用实例#栈&单链表#简易计算器
    数据结构应用实例#栈#迷宫寻路
    数据结构笔记#栈
    #2028 Lowest Common Multiple Plus
    数据结构笔记#单链表
    #2018 母牛的故事
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822494.html
Copyright © 2011-2022 走看看