TCS MockVita 2019 Round 2问题:跳游戏

时间:2019-06-17 18:39:35

标签: c++ algorithm dynamic-programming

我正在尝试解决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,并且不使用双跳< / p>

示例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()

我希望您能在我的代码中找到错误并给出正确的解决方案,以及任何使该解决方案失败的测试用例。谢谢:)

1 个答案:

答案 0 :(得分:1)

您不需要任何地图。您需要记住的是最后几个最大值。每步都有两个选择(前两个除外),最后跳两次或不跳两次。如果您不希望做DJ,则最好的选择是最大结石+当前和结石前+ 2 *当前max(no_dj[2] + arr[i], no_dj[1] + 2 * arr[i])中的最大值。

另一方面,如果要制作dj而不是拥有三个选项,请跳过前一个dj dj[2] + arr[i]之后的一块石头,或者跳过dj dj[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]);
}

您需要记住的是三个元素组成的两个数组。两次跳后的最后三个最大值和没有两次跳的最后三个最大值。