首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【华为OD-E卷 -68 玩牌高手 100分(python、java、c++、js、c)】

  • 25-03-07 19:22
  • 3338
  • 9068
blog.csdn.net

【华为OD-E卷 - 玩牌高手 100分(python、java、c++、js、c)】

题目

给定一个长度为n的整型数组,表示一个选手在n轮内可选择的牌面分数。选手基于规则选牌,
请计算所有轮结束后其可以获得的最高总分数。
选择规则如下:
在每轮里选手可以选择获取该轮牌面,则其总分数加上该轮牌面分数,为其新的总分数。 选手也可不选择本轮牌面直接跳到下一轮,此时将当前总分数还原为3轮前的总分数,若当前轮次小于等于3(即在第1、2、3轮选择跳过轮次),则总分数置为0。 选手的初始总分数为0,且必须依次参加每一轮

输入描述

  • 第一行为一个小写逗号分割的字符串,表示n轮的牌面分数,1<= n <=20。

分数值为整数,-100 <= 分数值 <= 100。

不考虑格式问题

输出描述

  • 所有轮结束后选手获得的最高总分数

用例

用例一:
输入:
1,-5,-6,4,3,6,-2
  • 1
输出:
11
  • 1

python解法

  • 解题思路:
  • 问题分析: 题目要求从一组卡牌中选择卡牌来获取最大得分,每次选择卡牌时,你可以选择当前卡牌或跳过几张卡牌。具体的规则是:

你可以选择当前卡牌并获得它的分数。
你也可以跳过当前卡牌,但跳过后,你必须至少跳过 2 张卡牌(即从当前卡牌跳到当前卡牌的下三张)。
任务是计算最大得分。

递归思路: 这道题目可以通过递归来解决。对于当前的卡牌 index,我们有两种选择:

选择当前卡牌: 选择卡牌的得分是当前卡牌的分数加上从 index-1 处计算得到的最大得分。
跳过当前卡牌: 直接跳到 index-3 处,计算从那一位置开始的最大得分。
递归的状态是 get_max_score(arr, index),其中 arr 是卡牌数组,index 是当前的卡牌位置。

动态规划优化: 由于递归可能会重复计算相同的子问题,因此使用 记忆化递归(Memoization) 来存储已经计算过的结果,避免重复计算,提升效率。

递归终止条件:

如果 index < 0,表示没有卡牌可以选择,返回 0。
如果 index 已经计算过了(即 index 存在于 memo 中),则直接返回 memo[index]。
最终解: 递归的最终结果是从最后一个卡牌开始,计算出最大得分。

# 定义递归函数,计算从第 index 张卡牌开始的最大得分
def get_max_score(arr, index, memo):
    # 递归终止条件:如果 index 小于 0,表示没有卡牌可以选择,返回 0
    if index < 0:
        return 0
    
    # 如果当前 index 的值已经计算过,直接返回记忆化的结果
    if index in memo:
        return memo[index]
    
    # 选择当前卡牌:取当前卡牌的分数 + 从 index - 1 处继续递归
    take = get_max_score(arr, index - 1, memo) + arr[index]
    
    # 跳过当前卡牌:跳到 index - 3 处继续递归
    skip = get_max_score(arr, index - 3, memo)
    
    # 取选择当前卡牌和跳过当前卡牌中的最大得分,并保存到 memo 中
    memo[index] = max(take, skip)
    
    # 返回当前 index 位置的最大得分
    return memo[index]

# 主程序:输入卡牌分数,并计算最大得分
cards = list(map(int, input().split(",")))  # 读取输入的卡牌分数并转换为列表
print(get_max_score(cards, len(cards) - 1, {}))  # 从最后一张卡牌开始,计算最大得分

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

java解法

  • 解题思路
  • 这道题目要求从一组卡牌分数中选择卡牌来获得最大得分,每次选择时,你可以选择当前卡牌或者跳过一些卡牌。具体的规则是:

每次选择卡牌,你可以选择当前卡牌并获得它的分数,或者跳过当前卡牌。
如果选择了当前卡牌,那么下一个选择会从上一个卡牌的下一个卡牌开始(即递归调用 currentRound-1)。
如果跳过当前卡牌,你需要跳过至少 2 张卡牌(即从 currentRound-3 开始计算)。
为了避免重复计算,我们使用 记忆化递归(Memoization),将已经计算过的子问题结果存储在 memo 中。通过使用 memo,可以将时间复杂度优化到 O(n),从而避免暴力递归中的重复计算。

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
    // 创建一个 HashMap 来存储已经计算过的子问题结果
    private static Map<Integer, Integer> memo = new HashMap<>();

    public static void main(String[] args) {
        // 创建 Scanner 对象来读取输入
        Scanner scanner = new Scanner(System.in);

        // 读取输入并将其按逗号分割为字符串数组
        String[] input = scanner.nextLine().split(",");

        // 将字符串数组转换为整型数组
        int[] points = new int[input.length];
        for (int i = 0; i < input.length; i++) {
            points[i] = Integer.parseInt(input[i]);
        }

        // 输出从最后一张卡牌开始,计算最大得分
        System.out.println(maxScore(points, points.length - 1));
    }

    // 计算从当前 round 开始能得到的最大得分
    private static int maxScore(int[] points, int currentRound) {
        // 如果当前 round 小于 0,表示没有卡牌可以选择,返回 0
        if (currentRound < 0) {
            return 0;
        }

        // 如果当前 round 的得分已经计算过,直接从 memo 中返回结果
        if (memo.containsKey(currentRound)) {
            return memo.get(currentRound);
        }

        // 选择当前卡牌:当前卡牌的分数 + 从 currentRound-1 开始递归计算的最大得分
        int choose = points[currentRound] + maxScore(points, currentRound - 1);

        // 跳过当前卡牌:跳到 currentRound-3 开始递归计算的最大得分
        // 如果 currentRound 小于 3,跳过卡牌就相当于返回 0
        int skip = (currentRound < 3) ? 0 : maxScore(points, currentRound - 3);

        // 当前 round 的最大得分是选择当前卡牌和跳过当前卡牌两种选择的最大值
        int result = Math.max(choose, skip);

        // 将结果保存到 memo 中,避免重复计算
        memo.put(currentRound, result);

        // 返回当前 round 的最大得分
        return result;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

C++解法

  • 解题思路
更新中
  • 1

C解法

  • 解题思路

更新中
  • 1

JS解法

  • 解题思路

  • 本题的目标是从给定的卡牌分数数组中选择卡牌,使得选择的卡牌总得分最大。每次选择卡牌时,有两个选择:

选择当前卡牌: 如果选择当前卡牌,就需要加上当前卡牌的得分,然后递归计算从当前卡牌的前一张开始的最大得分。
跳过当前卡牌: 如果跳过当前卡牌,必须跳过至少 2 张卡牌,即从 currentRound-3 开始递归计算。
为了避免重复计算,我们可以使用 记忆化递归(Memoization) 来存储已经计算过的子问题的结果,从而提升效率。

思路概述:
使用递归函数 maxScore(points, currentRound) 计算从 currentRound 开始到最后一张卡牌的最大得分。
如果当前卡牌已被计算过,则直接从 memo 中获取结果。
对于每张卡牌,有两种选择:选择当前卡牌或者跳过当前卡牌。
将每次计算的结果存入 memo,以避免重复计算,提高效率

'use strict';

// 创建一个 Map 来存储已经计算过的结果(记忆化)
const memo = new Map();

// 递归函数:计算从 currentRound 开始的最大得分
const maxScore = (points, currentRound) => {
    // 如果当前回合小于 0,表示没有卡牌可以选择,返回 0
    if (currentRound < 0) {
        return 0;
    }

    // 如果当前回合已经计算过结果,直接从 memo 中返回
    if (memo.has(currentRound)) {
        return memo.get(currentRound);
    }

    // 选择当前卡牌:当前卡牌得分 + 从 currentRound-1 继续计算最大得分
    const choose = points[currentRound] + maxScore(points, currentRound - 1);

    // 跳过当前卡牌:跳到 currentRound-3 继续计算最大得分
    // 如果 currentRound 小于 3,跳过卡牌就相当于返回 0
    const skip = currentRound < 3 ? 0 : maxScore(points, currentRound - 3);

    // 当前回合的最大得分是选择当前卡牌和跳过当前卡牌中的最大值
    const result = Math.max(choose, skip);

    // 将当前回合的最大得分保存到 memo 中
    memo.set(currentRound, result);

    // 返回当前回合的最大得分
    return result;
};

// 主程序:处理输入并调用 maxScore 函数
const main = () => {
    // 让 stdin 持续接收输入数据
    process.stdin.resume();
    process.stdin.setEncoding('utf-8');

    let input = '';
    
    // 接收每次输入的块数据
    process.stdin.on('data', (chunk) => {
        input += chunk;
    });

    // 输入结束时调用回调函数
    process.stdin.on('end', () => {
        // 处理输入,去除两端空格,并按逗号分割,转换为数字数组
        const points = input.trim().split(',').map(Number);
        
        // 调用 maxScore 函数,从最后一张卡牌开始,计算最大得分
        console.log(maxScore(points, points.length - 1));
    });
};

// 执行主函数
main();

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

注:本文转载自blog.csdn.net的CodeClimb的文章"https://blog.csdn.net/CodeClimb/article/details/145099435"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top