Stone Game

[3, 4, 5, 6] 每次合并两个石子,所需最少代价。

[3, 9, 6] --> 9

[12, 6] --> 12

[18] --> 18

9 + 12 + 18 = 39

Solution

记忆化搜索的思路,从大到小,先考虑最后的0-n-1合并的总花费

state: dp[i][j]表示把第i到第j个石子合并到一起的最小花费

Function: 预处理sum[i][j]表示i到j所有石子价值和 dp[i][j] = min(dp[i][k] + dp[k+1][j] + sum[i][j]) k表示i..j的可分割点

Code

class Solution {
public:
    /**
     * @param A an integer array
     * @return an integer
     */
    int stoneGame(vector<int>& A) {
        // Write your code here
        if(A.size() == 0)
        {
            return 0;
        }

        int n = A.size();

        vector<vector<int>> dp;
        vector<vector<bool>> flag;
        vector<vector<int>> sum;
        for(int i = 0; i<n; i++)
        {
            vector<int> tmp(n, 0);
            vector<bool> tmp2(n, false);
            dp.push_back(tmp);
            flag.push_back(tmp2);

            vector<int> tmp3(n, 0);
            tmp3[i] = A[i];
            sum.push_back(tmp3);
        }

        for(int i = n-1; i >= 0; i--)
        {
            for(int j = i+1; j<n; j++)
            {
                sum[i][j] = sum[i][j-1] + sum[j][j];
            }
        }

        /*
        int ret = memSearch(dp, flag, sum, 0, n-1);
        for(int i = 0; i<dp.size(); i++)
        {
            for(int j = 0; j<dp[i].size(); j++)
            {
                cout<<dp[][]
            }
        }*/

        return memSearch(dp, flag, sum, 0, n-1);
    }

    int memSearch(vector<vector<int>>& dp, vector<vector<bool>>& flag, vector<vector<int>>& sum, int l, int r)
    {
        if(flag[l][r] == true)
        {
            return dp[l][r];
        }

        if(l == r)
        {
            return 0;
        }

        flag[l][r] = true;
        dp[l][r] = numeric_limits<int>::max();

        for(int i = l; i < r; i++)
        {
            dp[l][r] = min(dp[l][r], memSearch(dp, flag, sum, l, i) + memSearch(dp, flag, sum, i+1, r) + sum[l][r]);
        }

        return dp[l][r];
    }
};

results matching ""

    No results matching ""