0
点赞
收藏
分享

微信扫一扫

玩牌高手(C 语言)

题目

给定一个长度为N的整数数组,表示一个选手在N轮内选择的牌面分数,
选手基于规则选牌,请计算所有轮结束后其可以获得的最高总分数。
选择规则如下:

  1. 在每轮里选手可以选择获取该轮牌面,则其总分数加上该轮牌面分数为其新的总分数
  2. 选手也可不选择本轮牌面,直接跳到下一轮,此时将当前总分数还原为 3 轮前的总分数,若当前轮次小于等于 3,则总分数置 0
  3. 选手初始总分数为 0,且必须依次参加每轮

输入

第一行为一个小写逗号分隔的字符串
表示N轮的牌面分数
1 <= N <= 20 分数值为整数 [-100,100]
不考虑格式问题

输出描述

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

示例一

输入

1,-5,-6,4,3,6,-2

输出

11

说明

总共7轮牌面,
第一轮选择该轮牌面总分数为1
第二轮不选择该轮牌面总分数还原为0
第三轮不选择该轮牌面总分数还原为0
第四轮选择该轮牌面总分数为4
第五轮选择该轮牌面总分数为7
第六轮选择该轮牌面总分数为13
第七轮如果不选择概论牌面 则总分数返回到三轮前的分数 即第四轮的总分数4
如果选择该轮牌面,总分数为11,所以选择该轮, 因此最高总分数为11

解题思路

  1. 读取输入:
    通过 fgets 函数从标准输入读取一行包含逗号分隔的整数字符串。然后使用 strtok 函数将字符串按逗号分割,并调用 atoi 将每个分割出的字符串转换成整数,存储到数组 scores 中。

  2. 定义状态数组:
    创建一个大小足够的状态数组 state,用于记录在每轮结束时选手可能获得的最大分数。数组下标表示当前轮次,值表示截止到该轮结束时的最大总分数。

  3. 计算每轮分数:
    使用循环遍历所有轮次(数组 scores 的元素)。

    • 对于前3轮,由于无法回溯至更早的轮次,直接累计当前分数即可,同时确保分数大于等于0。
    • 从第4轮开始,每次都需要比较两种选择:
      a) 当前分数加上本轮分数
      b) 直接回溯到三轮前的分数
      选取两者中较大的作为新的当前分数,存储在 state[i] 中。
  4. 返回最大总分数:
    循环结束后,state[n-1] 即为经过所有轮次后选手能获得的最高总分数。

  5. 主函数处理:
    主函数 main 负责读取用户输入、处理数据并将最终结果传给 max_score 函数进行计算,最后输出计算得到的最高总分数。

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义数组最大长度,这里假设输入的轮数最多为20轮
#define MAX_LEN 100

// 定义一个函数 max_score,接收整数数组 scores 和其长度 n 作为参数
// 返回按照选牌规则计算的所有轮结束后选手能获得的最高总分数
int max_score(int *scores, int n) {
    // 初始化一个状态数组 state,大小为 1024,用于存储每轮结束时可能的最大分数
    int state[MAX_LEN] = {0};

    // 遍历所有轮次
    for (int i = 0; i < n; ++i) {
        // 第一轮时,直接将第一张牌面分数赋值给 state[0]
        if (i == 0) {
            state[0] = scores[0];
        }
        // 对于前3轮(包括第3轮),由于无法回溯到更早的轮次,只需累计当前分数
        if (i < 3) {
            state[i] = state[i - 1] + scores[i];
            // 确保分数大于等于0
            state[i] = (state[i] > 0 ? state[i] : 0);
        }
        // 从第4轮开始,可以进行回溯选择,取“当前分数加上本轮分数”与“三轮前的分数”中较大的那个
        else {
            int a = state[i - 1] + scores[i]; // 当前分数加上本轮分数
            int b = state[i - 3];             // 三轮前的分数
            state[i] = (a > b ? a : b); // 取较大者作为新的当前分数
        }
    }

    // 返回最后一轮的最高总分数
    return state[n - 1];
}

int main() {
    // 读取一行输入数据
    char input[MAX_LEN];
    fgets(input, MAX_LEN, stdin);
    // 移除末尾换行符
    input[strcspn(input, "\n")] = '\0';

    // 初始化一个数组 scores 来存储每轮的牌面分数
    int scores[20];
    // 初始化计数器 count,用于记录读入的有效分数个数
    int count = 0;

    // 使用 strtok 函数按逗号分隔读取每一轮的分数并转换为整数存入 scores 数组
    char *token = strtok(input, ",");
    while (token != NULL) {
        scores[count++] = atoi(token);
        token = strtok(NULL, ",");
    }

    // 调用 max_score 函数计算并输出最高总分数
    printf("%d\n", max_score(scores, count));
    return 0;
}

文章目录

举报

相关推荐

0 条评论