TCS 模拟生活 2019 第 2 轮问题:跳跃游戏

TCS MockVita 2019 Round 2 Question: Hop Game

本文关键字:问题 跳跃 游戏 模拟 生活 2019 TCS      更新时间:2023-10-16

我正在尝试解决TCS MockVita 2019第2轮中提出的问题:

问题描述

高斯学校的数学老师Felix Kline博士介绍了以下游戏来教他的学生解决问题。他将一系列"跳石"(纸片)排成一条线,每块石头上都标有点(正数)。

学生从一端开始,跳到另一端。一个人可以踩到一块石头,将石头上的数字添加到他们的累积分数中,或者跳过一块石头,落在下一块石头上。在这种情况下,他们得到的分数是他们降落的石头上标记的两倍,但没有得到他们跳过的石头上标记的分数。

在旅程中最多一次,学生被允许(如果他们选择)进行"双跳"——也就是说,他们跳过两块连续的石头——在那里他们将获得他们落在的石头上的三倍的点,但不是他们跳过的石头的点。

老师希望他的学生做一些思考,并提出一个计划,以获得尽可能高的分数。给定石头序列上的数字,编写一个程序来确定可能的最高分数。

约束

序列中的宝石数量<30

输入格式

第一行包含 N,整数的个数(这是一个正整数)

下一行包含用逗号分隔的 N 个点(每个点都是正整数)。这些是石头上按石头放置顺序排列的点。

输出

一个整数表示最高分

测试用例

解释

例 1

输入

3

4,2,3

输出

10

解释

有 3 块石头 (N=3),点(按布局顺序)分别为 4、2 和 3。

如果我们踩到第一块石头并跳过第二块石头得到 4 + 2 x 3 = 10。双跳到第三块石头只会得到 9。因此结果为 10,并且不使用双跳

例 2

输入

6

4,5,6,7,4,5

输出

35

解释

N=6,并给出点的顺序。获得 35 的一种方法是从两次跳到石头 3 (3 x 6=18) 开始,转到石头 4 (7) 并跳到石头 6(10 分),总共 35 分。双跳只用了一次,结果是35。

我发现这是一个动态编程问题,但我不知道我做错了什么,因为我的解决方案无法通过所有测试用例。我的代码通过了我创建的所有测试。

unordered_map<int, int> lookup;
int res(int *arr, int n, int i){
if(i == n-1){
return 0;
}
if(i == n-2){
return arr[i+1];
}
if(lookup.find(i) != lookup.end())
return lookup[i];
int maxScore = 0;
if(i< n-3 && flag == false){
flag = true;
maxScore = max(maxScore, 3 * (arr[i+3]) + res(arr, n, i+3));
flag = false;
}
maxScore = max(maxScore, (arr[i+1] + res(arr,n,i+1)));
lookup[i] = max(maxScore, 2 * (arr[i+2]) + res(arr, n, i+2));
return lookup[i];
}
cout << res(arr, n, 0) + arr[0];  // It is inside the main()

我希望你能在我的代码中找到错误并提供正确的解决方案,以及任何未能通过此解决方案的测试用例。谢谢:)

你不需要任何地图。您需要记住的是最后几个最大值。你每个动作有两个选项(除了两个第一个),以双跳结束或不做它。如果你不想做一个DJ,那么你最好的快乐是最后一块石头+电流和最后一块石头+2 *当前max(no_dj[2] + arr[i], no_dj[1] + 2 * arr[i])之前的最大石头。

另一方面,如果你想制作 dj,那么你有三个选择,要么在之前的 djdj[2] + arr[i]后跳一块石头,要么在一些 djdj[1] + 2 * arr[i]后跳过最后一块石头,或者在当前的移动no_dj[0] + 3 * arr[i]中做双跳。

int res(int *arr, int n){
int no_dj[3]{ 0, 0, arr[0]};
int dj[3]{ 0, 0, 0};
for(int i = 1; i < n; i++){
int best_nodj = max(no_dj[1] + 2 * arr[i], no_dj[2] + arr[i]);
int best_dj = 0;
if(i > 1) best_dj = max(max(dj[1] + 2 * arr[i], dj[2] + arr[i]), no_dj[0] + 3 * arr[i]);
no_dj[0] = no_dj[1];
no_dj[1] = no_dj[2];
no_dj[2] = best_nodj;
dj[0] = dj[1];
dj[1] = dj[2];
dj[2] = best_dj;
}
return max(no_dj[2], dj[2]);
}

您所要记住的只是两个由三个元素组成的数组。双跳后的最后三个最大值和没有双跳后的最后三个最大值。