LeetCode每日一题(1000. Minimum Cost to Merge Stones)

There are n piles of stones arranged in a row. The ith pile has stones[i] stones.

A move consists of merging exactly k consecutive piles into one pile, and the cost of this move is equal to the total number of stones in these k piles.

Return the minimum cost to merge all piles of stones into one pile. If it is impossible, return -1.

Example 1:

Input: stones = [3,2,4,1], k = 2
Output: 20

Explanation:
We start with [3, 2, 4, 1].
We merge [3, 2] for a cost of 5, and we are left with [5, 4, 1].
We merge [4, 1] for a cost of 5, and we are left with [5, 5].
We merge [5, 5] for a cost of 10, and we are left with [10].
The total cost was 20, and this is the minimum possible.

Example 2:

Input: stones = [3,2,4,1], k = 3
Output: -1

Explanation: After any merge operation, there are 2 piles left, and we can’t merge anymore. So the task is impossible.

Example 3:

Input: stones = [3,5,1,2,6], k = 3
Output: 25

Explanation:
We start with [3, 5, 1, 2, 6].
We merge [5, 1, 2] for a cost of 8, and we are left with [3, 8, 6].
We merge [3, 8, 6] for a cost of 17, and we are left with [17].
The total cost was 25, and this is the minimum possible.

Constraints:

  • n == stones.length
  • 1 <= n <= 30
  • 1 <= stones[i] <= 100
  • 2 <= k <= 30

假设 dp[i][j][k]是从 stones[i]到 stones[j]合并为 k 个堆所需要的成本

然后我们把整个合并过程反过来想

最后一步一定是将 k 个堆合并为 1 个堆: dp[i][j][1] = dp[i][j][k] + sum(i,j)

将 stones[i…=j]合并为 k 个堆, 从 i…j 范围中挑选任意一个 m, 左侧为 stones[i…=m], 右侧为 stones[m+1…=j], 左侧合并为 k-1 个堆的成本加上右侧合并为 1 个堆的成本就是整体合并为 k 个堆的成本, dp[i][j][k] = min(dp[i][m][k-1], dp[m+1][j][1])



use std::collections::HashMap;

impl Solution {
    fn check(length: i32, k: i32) -> bool {
        if length < k {
            return false;
        }
        if length == k {
            return true;
        }
        Solution::check(length - k + 1, k)
    }

    fn dp(stones: &Vec<i32>, k: usize, i: usize, j: usize, n: usize, cache: &mut HashMap<(usize, usize, usize), i32>) -> i32 {
        if let Some(&c) = cache.get(&(i, j, n)) {
            return c;
        }
        if i == j {
            if n == 1 {
                return 0;
            }
            return i32::MAX;
        }
        if n == 1 {
            if j - i + 1 == k {
                let sum = stones[i..=j].into_iter().sum();
                cache.insert((i, j, n), sum);
                return sum;
            }
            let next = Solution::dp(stones, k, i, j, k, cache);
            if next == i32::MAX {
                return i32::MAX;
            }
            let ans = next + stones[i..=j].into_iter().sum::<i32>();
            cache.insert((i, j, n), ans);
            return ans;
        }
        let mut ans = i32::MAX;
        for m in i..j {
            let left = Solution::dp(stones, k, i, m, n - 1, cache);
            if left == i32::MAX {
                continue;
            }
            let right = Solution::dp(stones, k, m + 1, j, 1, cache);
            if right == i32::MAX {
                continue;
            }
            ans = ans.min(left + right);
        }
        cache.insert((i, j, n), ans);
        ans
    }
    pub fn merge_stones(stones: Vec<i32>, k: i32) -> i32 {
        if stones.len() == 1 {
            return 0;
        }
        if !Solution::check(stones.len() as i32, k) {
            return -1;
        }
        Solution::dp(&stones, k as usize, 0, stones.len() - 1, 1, &mut HashMap::new())
    }
}

你可能感兴趣的:(数据结构,算法,leetcode,算法,职场和发展)