1. 程式人生 > 其它 >最後一塊石頭的重量||

最後一塊石頭的重量||

題目連結:https://leetcode-cn.com/problems/last-stone-weight-ii
題目描述:
有一堆石頭,用整數陣列stones 表示。其中stones[i] 表示第 i 塊石頭的重量。
每一回合,從中選出任意兩塊石頭,然後將它們一起粉碎。假設石頭的重量分別為x 和y,且x <= y。那麼粉碎的可能結果如下:
如果x == y,那麼兩塊石頭都會被完全粉碎;
如果x != y,那麼重量為x的石頭將會完全粉碎,而重量為y的石頭新重量為y-x。
最後,最多隻會剩下一塊 石頭。返回此石頭 最小的可能重量 。如果沒有石頭剩下,就返回 0。

示例 1:
輸入:stones = [2,7,4,1,8,1]
輸出:1
解釋:
組合 2 和 4,得到 2,所以陣列轉化為 [2,7,1,8,1],
組合 7 和 8,得到 1,所以陣列轉化為 [2,1,1,1],
組合 2 和 1,得到 1,所以陣列轉化為 [1,1,1],
組合 1 和 1,得到 0,所以陣列轉化為 [1],這就是最優值。

示例 2:
輸入:stones = [31,26,33,21,40]
輸出:5

示例 3:
輸入:stones = [1,2]
輸出:1

提示:
1 <= stones.length <= 30
1 <= stones[i] <= 100

題解:
本題是儘量讓石頭分成重量相同的兩堆,相撞之後剩下的石頭最小,這樣就化解成01揹包問題了。


class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum = 0;
        for(int &item : stones)
        {
            sum += item; 
        }
        int target = sum / 2;
        vector<int> dp(1501, 0);  //dp[j]:容量為j時,揹包所裝的石頭總和為dp[j]
        for(int i = 0; i < stones.size(); i++)
        {
            for(int j = target; j>= stones[i]; j--)
            {
                dp[j] = max(dp[j], dp[j - stones[i]] +  stones[i]);
            }
        }
        return (sum - dp[target]) - dp[target];

    }
};