• 题解 P1541 【乌龟棋】


    题目描述

    乌龟棋的棋盘是一行(N)个格子,每个格子上一个分数(非负整数)。棋盘第(1)格是唯一的起点,第(N)格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。

    乌龟棋中(M)张爬行卡片,分成(4)种不同的类型 ,每种类型的卡片上分别标有 (1,2,3,4) 四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。

    游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。

    很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。

    现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
    题目链接

    思路

    我们发现,每种卡片的数量很少,并且我们的移动格数只和我们使用的牌有关,所以我们可以考虑将每一种牌的使用数量作为状态来进行(DP) 。我们假设 (dp[p_1][p_2][p_3][p_4])​表示标有(1)的卡使用了(p_1)张,……,标有(4) 的卡使用了(p_4) 张所能获得的最大分。

    接下来考虑状态如何转移。

    记当前位置 (place=1+p_1+2p_2+3p_3+p_4)。我们考虑当前状态下上一次用了哪一种卡片。

    如果 (p_1le 0) ,那么最后一次可以使用了一张标有 (1) 的卡片,此时(dp[p_1][p_2][p_3][p_4]=dp[p_1][p_2][p_3][p_4]+a[place])
    如果 (p_2le 0) ,那么 (dp[p_1][p_2][p_3][p_4] = dp[p_1][p_2 - 1][p_3][p_4] + a[place])
    如果 (p_3le 0) ,那么 (dp[p_1][p_2][p_3][p_4] = dp[p_1][p_2][p_3 - 1][p_4] + a[place])
    如果 (p_4le 0) ,那么 (dp[p_1][p_2][p_3][p_4] = dp[p_1][p_2][p_3][p_4 - 1] + a[place])
    程序实现中四者取最大值即可。

    初始条件为:(dp[0][0][0][0] = a[1]) ,即不使用任何卡片时,在第一格,自动获得了第一格的分数。

    假设给出的标有 (1,2,3,4) 的卡片数量分别为 (n_1,n_2,n_3,n_4),那么最终答案就是 (dp[n_1][n_2][n_3][n_4])

    (n_1,n_2,n_3,n_4)​ 可以放在一个数组中,因此最终总体复杂度约为 (Theta((frac{m}{4})^4))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=360;
    const int M=45;
    int k,m;
    int a[N],dp[M][M][M][M];
    int n[5];
    int main() {
        cin>>k>>m;
        for(int i=1;i<=k;i++) cin>>a[i];
        for(int i=1;i<=m;i++) {
            int x;
            cin>>x;
            n[x]++;
        }
        dp[0][0][0][0]=a[1]; //初始化
        for(int p1=0;p1<=n[1];p1++) {
            for(int p2=0;p2<=n[2];p2++) {
                for(int p3=0;p3<=n[3];p3++) {
                    for(int p4=0;p4<=n[4];p4++) {
                        int place=1+p1+2*p2+3*p3+4*p4;
                        if(p1>0) dp[p1][p2][p3][p4]=max(dp[p1][p2][p3][p4],dp[p1-1][p2][p3][p4]+a[place]);
                        if(p2>0) dp[p1][p2][p3][p4]=max(dp[p1][p2][p3][p4],dp[p1][p2-1][p3][p4]+a[place]);
                        if(p3>0) dp[p1][p2][p3][p4]=max(dp[p1][p2][p3][p4],dp[p1][p2][p3-1][p4]+a[place]);
                        if(p4>0) dp[p1][p2][p3][p4]=max(dp[p1][p2][p3][p4],dp[p1][p2][p3][p4-1]+a[place]);
                    }
                }
            }
        }
        cout<<dp[n[1]][n[2]][n[3]][n[4]]<<endl;
        return 0;
    }
    
  • 相关阅读:
    深入理解 Java中的 流 (Stream)
    算法学习
    编译Opencv的GPU,利用CUDA加速
    【linux】【windows】查看你想访问的电脑Ip 和 端口是否 通畅
    【docker】centos7 上拉取docker镜像,一直拉取不到,报错:Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while w
    【mybatis】标签条件中判断入参属性值是否包含子字符串
    【java】Java多线程总结之线程安全队列Queue【转载】
    【spring boot】【redis】spring boot 集成redis的发布订阅机制
    【spring boot】spring boot 基于redis pipeline 管道,批量操作redis命令
    【java】java删除文件delete和deleteOnExit 方法的区别,为什么调用deleteOnExit无效?
  • 原文地址:https://www.cnblogs.com/Ryan-juruo/p/13941767.html
Copyright © 2020-2023  润新知