1.题目:
A game for one player is played on a board consisting of N consecutive squares, numbered from 0 to N − 1. There is a number written on each square. A non-empty zero-indexed array A of N integers contains the numbers written on the squares. Moreover, some squares can be marked during the game.
At the beginning of the game, there is a pebble on square number 0 and this is the only square on the board which is marked. The goal of the game is to move the pebble to square number N − 1.
During each turn we throw a six-sided die, with numbers from 1 to 6 on its faces, and consider the number K, which shows on the upper face after the die comes to rest. Then we move the pebble standing on square number I to square number I + K, providing that square number I + K exists. If square number I + K does not exist, we throw the die again until we obtain a valid move. Finally, we mark square number I + K.
After the game finishes (when the pebble is standing on square number N − 1), we calculate the result. The result of the game is the sum of the numbers written on all marked squares.
For example, given the following array:
A[0] = 1 A[1] = -2 A[2] = 0 A[3] = 9 A[4] = -1 A[5] = -2
one possible game could be as follows:
- the pebble is on square number 0, which is marked;
- we throw 3; the pebble moves from square number 0 to square number 3; we mark square number 3;
- we throw 5; the pebble does not move, since there is no square number 8 on the board;
- we throw 2; the pebble moves to square number 5; we mark this square and the game ends.
The marked squares are 0, 3 and 5, so the result of the game is 1 + 9 + (−2) = 8. This is the maximal possible result that can be achieved on this board.
Write a function:
int solution(int A[], int N);
that, given a non-empty zero-indexed array A of N integers, returns the maximal result that can be achieved on the board represented by array A.
For example, given the array
A[0] = 1 A[1] = -2 A[2] = 0 A[3] = 9 A[4] = -1 A[5] = -2
the function should return 8, as explained above.
Assume that:
- N is an integer within the range [2..100,000];
- each element of array A is an integer within the range [−10,000..10,000].
Complexity:
- expected worst-case time complexity is O(N);
- expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
Copyright 2009–2015 by Codility Limited. All Rights Reserved. Unauthorized copying, publication or disclosure prohibited.
2.题目分析
这个题目写的超级复杂,其实说的内容很简单,就是我们掷骰子,1~6,代表向前走几步。那么一个棋盘的长度为N,每个节点上有一个数字,我们要通过掷色子刚好走到最后一个格子,在这个过程中会经过x个点。问题就是要我们输出这x个点最大可能的和是多少。
这个题如果不是看了关于dynamicprogramming的介绍的话一下子就蒙傻逼了。这个可能小多啊,跳到所有的正数是没话说,不过因为有负数,如何选择我跳入那个负数,避开哪个负数?如果有一长串的负数我如何跳入?更何况时间复杂度要求为O(N)。。这。。头好大。
但是有了dynamic这个算法,我们便可以换一个思路来向这个问题。
我们并不是要向后看,而是向前看。有点数学归纳法的赶脚。
首先,我们随便的站到位置W上。那么,如果要到达这个点,只能是从其前6个位置跳过来的,因为色子最大就到6呢。
那么如果问题到这个点结束,因为W位置上的数字是固定的,那么要跳到这个点时和为最大,则需要找到前六个点中的最大值即可。那么以此类推,最终会回到第0个位置。这个位置的最大值是固定的就是其本身。我们便可以递推的推出所有位置的最大值~
而且我们在每一个位置,内循环查找的最大次数为6,所以即使我有两层循环,那么时间复杂度也只是6N~=O(N)。线性。
我们还需要一个数组存储每一个位置的最大值需要N个空间。
3.代码
int maxLastSix(int A[],int pos) { int step=1; int result = A[pos-step]; while((pos-step)>=0) { if(step>6) { return result; } result = (result>A[pos-step])?result:A[pos-step]; step++; } return result; } int solution(int A[], int N) { // write your code in C99 int dp[N]; int i=0; dp[0]=A[0]; for(i=1;i<N;i++) { int temp = maxLastSix(dp,i); dp[i]=A[i]+temp; // printf("%d\n",temp); } return dp[N-1]; }