본문 바로가기
leetcode

leetcode 1563 - Stone Game V

by 초특급하품 2020. 11. 25.

https://leetcode.com/problems/stone-game-v/

풀이

Alice가 임의의 크기로 left와 right를 나눠서 더 작은 쪽의 점수를 얻으면, 그 뒤로 더 작은 쪽에서 같은 게임이 반복된다. 따라서 모든 크기로 나눠보고 재귀적으로 게임을 진행시킬 수 있다. 이 게임은 마지막 하나가 남을 때까지 진행되며 그 상태에서 Alice는 0점을 얻는다. 

 

모든 subgame은 stoneValue의 subarray에서 이루어지기 때문에 중복된 연산을 방지하기 위해 아래와 같이 d 배열을 정의한다.

d[i][j] = stoneValue의 [i, j] 부분에서 게임할 때 Alice가 얻는 최대 점수

 

매 subgame에서 가능한 경우를 탐색할 때 미리 구해놓은 sum 배열을 활용하면 좀 더 효율적으로 구할 수 있다.

 

 

코드

class Solution {
public:
    vector<vector<int>> d;
    vector<int> sum;
    int stoneGameV(vector<int>& stoneValue) {
        int n = stoneValue.size();
        d.resize(n, vector<int>(n, -1));
        sum.resize(n+1);
        
        for(int i = 0; i < n; i++) {
            sum[i+1] = sum[i] + stoneValue[i];
        }
        
        return dfs(0, n-1);
    }
    
    int dfs(int start, int end) {
        if(d[start][end] != -1) return d[start][end];
        if(start == end) return d[start][end] = 0;
    
        int best = 0;
        for(int i = start; i < end; i++) {
            int leftSum = sum[i+1] - sum[start];
            int rightSum = sum[end+1] - sum[i+1];

            if(leftSum < rightSum) {
                best = max(best, leftSum + dfs(start, i));
            } else if(leftSum > rightSum) {
                best = max(best, rightSum + dfs(i+1, end));
            } else {
                best = max(best, max(leftSum + dfs(start, i), rightSum + dfs(i+1, end)));
            }
        }
        return d[start][end] = best;
    }
};

'leetcode' 카테고리의 다른 글

leetcode 1510 - Stone Game IV  (0) 2020.11.25
leetcode 1406 - Stone Game III  (0) 2020.11.24
leetcode 1140 - Stone Game II  (0) 2020.11.23
leetcode 877 - Stone Game  (0) 2020.11.22
leetcode 1326 - Minimum Number of Taps to Open to Water a Garden  (0) 2020.11.22

댓글