题目
给定一个长度为N
的整数数组,表示一个选手在N
轮内选择的牌面分数,
选手基于规则选牌,请计算所有轮结束后其可以获得的最高总分数。
选择规则如下:
- 在每轮里选手可以选择获取该轮牌面,则其总分数加上该轮牌面分数为其新的总分数
- 选手也可不选择本轮牌面,直接跳到下一轮,此时将当前总分数还原为 3 轮前的总分数,若当前轮次小于等于 3,则总分数置 0
- 选手初始总分数为 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
解题思路
-
读取输入:
通过fgets
函数从标准输入读取一行包含逗号分隔的整数字符串。然后使用strtok
函数将字符串按逗号分割,并调用atoi
将每个分割出的字符串转换成整数,存储到数组scores
中。 -
定义状态数组:
创建一个大小足够的状态数组state
,用于记录在每轮结束时选手可能获得的最大分数。数组下标表示当前轮次,值表示截止到该轮结束时的最大总分数。 -
计算每轮分数:
使用循环遍历所有轮次(数组scores
的元素)。- 对于前3轮,由于无法回溯至更早的轮次,直接累计当前分数即可,同时确保分数大于等于0。
- 从第4轮开始,每次都需要比较两种选择:
a) 当前分数加上本轮分数
b) 直接回溯到三轮前的分数
选取两者中较大的作为新的当前分数,存储在state[i]
中。
-
返回最大总分数:
循环结束后,state[n-1]
即为经过所有轮次后选手能获得的最高总分数。 -
主函数处理:
主函数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;
}