[GESP202312 六级] 闯关游戏

题目描述

你来到了一个闯关游戏。

这个游戏总共有 N N N 关,每关都有 M M M 个通道,你需要选择一个通道并通往后续关卡。其中,第 i i i 个通道可以让你前进 a i a_i ai 关,也就是说,如果你现在在第 x x x 关,那么选择第 i i i 个通道后,你将直接来到第 x + a i x+a_i x+ai 关(特别地,如果 x + a i ≥ N x + a_i \geq N x+aiN,那么你就通关了)。此外,当你顺利离开第 s s s 关时,你还将获得 b s b_s bs 分。

游戏开始时,你在第 0 0 0 关。请问,你通关时最多能获得多少总分。

输入格式

第一行两个整数 N N N M M M,分别表示关卡数量和每关的通道数量。

接下来一行 M M M 个用单个空格隔开的整数 a 0 , a 1 ⋯   , a M − 1 a_0,a_1\cdots,a_{M-1} a0,a1,aM1。保证 1 ≤ a i ≤ N 1\le a_i \le N 1aiN

接下来一行 N N N 个用单个空格隔开的整数 b 0 , b 1 ⋯   , b N − 1 b_0,b_1\cdots,b_{N-1} b0,b1,bN1。保证 ∣ b i ∣ ≤ 1 0 5 |b_i|\le 10^5 bi105

输出格式

一行一个整数,表示你通关时最多能够获得的分数。

输入输出样例 #1

输入 #1

6 2 
2 3
1 0 30 100 30 30

输出 #1

131

输入输出样例 #2

输入 #2

6 2
2 3
1 0 30 100 30 -1

输出 #2

101

说明/提示

样例解释 1

你可以在第 0 0 0 关选择第 1 1 1 个通道,获得 1 1 1 分并来到第 3 3 3 关;随后再选择第 0 0 0 个通道,获得 100 100 100 分并来到第 5 5 5 关;最后任选一个通道,都可以获得 30 30 30 分并通关。如此,总得分为 1 + 100 + 30 = 131 1+100+30=131 1+100+30=131

样例解释 2

请注意,一些关卡的得分可能是负数。

数据范围

对于 20 % 20\% 20% 的测试点,保证 M = 1 M=1 M=1

对于 40 % 40\% 40% 的测试点,保证 N ≤ 20 N \le 20 N20;保证 M ≤ 2 M\le 2 M2

对于所有测试点,保证 1 ≤ N ≤ 1 0 4 1 \le N \le 10^4 1N104;保证 1 ≤ M ≤ 100 1 \le M\le 100 1M100

提交链接

闯关游戏

解析

搜索的想法(40分)

深度优先搜索(DFS) 来枚举所有可能的路径,以找到通关时的最高得分。

主要逻辑

  1. dfs(pos, score)
  • pos 代表当前关卡编号
  • score 代表目前的累计得分
  • 递归终止条件:当 pos >= n(即通关)时,更新 mx 记录的最大得分。
  • 否则,尝试 m 种通道,每种都递归调用 dfs(pos + a[i], score + b[pos])
  1. main()
  • 读取输入 N N N, M M M(关卡数和通道数)。
  • 读取每个通道的跳跃距离 a [ i ] a[i] a[i]
  • 读取每一关的得分 b [ i ] b[i] b[i]
  • 调用 dfs(0, 0)0 关开始搜索所有可能的通关路径。

时间复杂度分析

最坏情况分析:在最坏情况下,DFS 会搜索所有可能的通关路径。

状态树的深度

  • 最深可能达到 N N N(最坏情况下一次只前进 1 1 1 关)。

每层的分支数

  • 每一层最多有 M M M 个选择(每一关有 M M M 个通道)。

搜索空间

  • 递归构成了一棵 最大深度 N N N,每个节点最多 M M M 个子节点 的搜索树。
  • 这样搜索树的节点数最多是 M N M^N MN(指数级别)。

对于 40 % 40\% 40% 的测试点,保证 N ≤ 20 N \le 20 N20;保证 M ≤ 2 M\le 2 M2,时间复杂度可以承受。

参考代码:

#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e4 + 9;

int n, m, a[109], b[MAX_N], mx = -1e9;  //mx初值为一个比较小的数(分数有负数存在)

int cost[10009];

void dfs(int pos, int score)
{
    if (pos >= n)
    {
        mx = max(mx, score);
        return;
    }
    for (int i = 0; i < m; i++)
        dfs(pos + a[i], score + b[pos]);
}
int main()
{
    cin >> n >> m; // 关卡的数量  每一关的通道数量
    for (int i = 0; i < m; i++)
        cin >> a[i]; // 第i个通道前进a[i]关
    for (int i = 0; i < n; i++)
        cin >> b[i]; // 通过第i关时获得的分数为b[i]
    dfs(0, 0);
    cout << mx;
    return 0;
}

动态规划的想法(100分)

动态规划(DP) 来代替深度优先搜索。动态规划能避免递归树的指数级别增长,优化到 O ( N ∗ M ) O(N*M) O(NM) 的复杂度。

使用一个一维 d p dp dp 数组来表示从第 x x x 关卡到达时的最大得分。然后通过迭代的方式,更新每个关卡的得分。

动态规划思路:

状态定义:

  • d p [ x ] dp[x] dp[x] 表示到达 x x x 关时的最大得分。

状态转移:

  • 从关卡 x x x 选择任意通道 i i i,到达 x + a [ i ] x + a[i] x+a[i] 关,得分更新为 d p [ x + a [ i ] ] = m a x ( d p [ x + a [ i ] ] , d p [ x ] + b [ x ] ) dp[x + a[i]] = max(dp[x + a[i]], dp[x] + b[x]) dp[x+a[i]]=max(dp[x+a[i]],dp[x]+b[x])

初始化:

  • d p [ 0 ] = 0 dp[0] =0 dp[0]=0(从第 0 0 0 关开始)。

目标:

  • 最终我们希望到达的关卡 ≥ n ≥n n,表示最后能通关时的最高得分。每一个 a [ i ] a[i] a[i] 最大为 n n n,我们可以求 d p [ n ] ∼ d p [ 2 ∗ n ] dp[n] \sim dp[2*n] dp[n]dp[2n] 的最大值即可。

参考代码:

#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e4 + 9;

int n, m, a[109], b[MAX_N], mx = -1e9;
int dp[2 * MAX_N]; // dp[i]:到达第i个关卡的最大分数

int main()
{
    cin >> n >> m; // 关卡的数量  每一关的通道数量
    for (int i = 1; i <= 2 * n; i++)
        dp[i] = -1e9;

    for (int i = 0; i < m; i++)
        cin >> a[i]; // 第i个通道前进a[i]关
    for (int i = 0; i < n; i++)
        cin >> b[i]; // 通过第i关时获得的分数为b[i]

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            dp[i + a[j]] = max(dp[i + a[j]], dp[i] + b[i]);

    for (int i = n; i <= 2 * n; i++)
        mx = max(mx, dp[i]);
    cout << mx;
    return 0;
}
GESP 2023 四级考试中涉及的“田忌赛马”的解题思路或者答案,这类竞赛题目通常来源于中国古典故事或历史事件,“田忌赛马”是一个著名的策略博弈案例。对于编程比赛而言,此问题可能被转化为一个算法挑战,要求参赛者编写一段代码来模拟最佳的比赛策略。 由于具体的试题内容和官方提供的标准解答不会公开在网络平台上,因此无法直接提供确切的答案。但是,可以给出一些通用的方法论指导,这可以帮助理解如何构建解决方案: 1. 分析原典故中的逻辑:在古文记载里,孙膑建议田忌采用非对称竞争的方式赢得胜利——即用自己的次好马来对抗对方最好的马,在其他两场比赛中则用自己最强的马去赢取对手较弱的马。这种策略的核心在于不对等资源分配下的最优选择。 2. 转化为计算模型:将实际场景抽象成数据结构(例如数组),其中每个元素代表一匹马的速度值;接着考虑怎样排列这些数值才能使得总得分最高。这里涉及到排序、比较以及贪心算法的应用。 3. 编写伪代码实现基本框架: ```python def tianji_race(horses_a, horses_b): # 假设horses_a是己方马匹列表,horses_b是对阵敌方马匹列表 # 对双方马匹按速度降序排序 sorted_horses_a = sorted(horses_a, reverse=True) sorted_horses_b = sorted(horses_b, reverse=True) score = 0 for i in range(len(sorted_horses_a)): if sorted_horses_a[i] > sorted_horses_b[i]: score += 1 elif sorted_horses_a[i] < sorted_horses_b[i]: score -= 1 return score ``` 请注意以上仅为简化版示例,并未完全覆盖所有情况及优化细节。针对特定版本的测试题还需要仔细阅读给定条件并调整相应参数设置。 为了获得更精确的信息,建议参考官方发布的指南或是联系赛事主办方获取正式的教学材料和支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值