我正在尝试解决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()
我希望您能在我的代码中找到错误并给出正确的解决方案,以及任何使该解决方案失败的测试用例。谢谢:)
答案 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]);
}
您需要记住的是三个元素组成的两个数组。两次跳后的最后三个最大值和没有两次跳的最后三个最大值。