1 条题解

  • 0
    @ 2025-8-24 21:59:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Mr_QwQ
    **

    搬运于2025-08-24 21:59:47,当前版本为作者最后更新于2018-05-10 14:09:26,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    毒矿万岁

    AC的第一道IOI题目,发个题解纪念一下。

    这个题是一个相当基础的dp,唯一的难点在于代码实现。

    令dp[i][a1][a2][b1][b2]为当前送第i辆车,第一个矿前两次送a1和a2,第二个前两次送b1和b2。

    然后直接看这辆车送第一个矿还是第二个就好了。

    边界是第n+1辆车,某个矿前两辆车没送的情况就直接用0占位就好。

    这里用的是记忆化,由于数据小,时空问题都不大。如果觉得记忆化可能会MLE/爆栈可以改用逆序dp(可以把i滚动掉),但是代码会复杂很多,不如记忆化好写,像我这样的萌新可以先用记忆化写一遍,再照着写dp。

    代码:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int n,type[100010],dp[100010][4][4][4][4];
    char ch;
    char getchar(int){
        char c='\0';
        while(c!='M' && c!='F' && c!='B')c=getchar();
        return c;
    }
    int food(char c){
        if(c=='M')return 1;
        if(c=='F')return 2;
        if(c=='B')return 3;
        return -1;
    }
    int coal(int fa,int fb,int fc){
        if(!fa && !fb)return 1;
        if(!fa)return (fb!=fc)+1;
        if(fa==fb && fb==fc)return 1;
        return (fa!=fb)+(fb!=fc)+(fa!=fc);
    }
    int dfs(int now,int a1,int a2,int b1,int b2){
        if(now>n)return 0;
        if(dp[now][a1][a2][b1][b2])return dp[now][a1][a2][b1][b2];
        return dp[now][a1][a2][b1][b2]=max(dfs(now+1,a2,type[now],b1,b2)+coal(a1,a2,type[now]),dfs(now+1,a1,a2,b2,type[now])+coal(b1,b2,type[now]));
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            ch=getchar(233);
            type[i]=food(ch);
        }
        printf("%d\n",dfs(1,0,0,0,0));
        return 0;
    }
    
    • 1

    信息

    ID
    3367
    时间
    1000ms
    内存
    18MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者