天池 在线编程 拿走瓶子(区间DP)

文章目录

1. 题目

描述
有n个瓶子排成一列,用arr表示。
你每次可以选择能够形成回文连续子串的瓶子拿走,剩下的瓶子拼接在一起。
返回你能拿走所有的瓶子的最小次数

n<=500 
arr[i]<=1000

示例

1:
输入:[1,3,4,1,5] 
输出:3 
说明:第一次先拿走[4],剩余[1,3,1,5]
第二次拿走[1,3,1],剩余[5]
第三次拿走[5]2:
输入:[1,2,3,5,3,1]
输出:2

来源:https://tianchi.aliyun.com/oj/141754208384739500/160296091929219254

2. 解题

  • 区间DP,dp[i][j] 表示区间 [i, j] 需要拿的最少次数
class Solution {
public:
    /**
     * @param arr: the array of bottles
     * @return: the minimum number of times you can take all the bottles
     */
    int takeAwayTheBottle(vector<int> &arr) {
        // Write your code here.
        int n = arr.size();
        if(n == 0)
            return 0;
        vector<vector<int>> dp(n, vector<int>(n, INT_MAX));
        for(int i = 0; i < n; i++)
            dp[i][i] = 1;//初始化长度为1的区间
        for(int i = 1; i < n; i++)
            if(arr[i-1] == arr[i])//初始化长度为2的区间
                dp[i-1][i] = 1;
            else
                dp[i-1][i] = 2;
        for(int len = 2; len < n; len++)
        {	// 区间长度
            for(int i = 0; i+len < n; i++)
            {
                int j = i+len;
                if(arr[i] == arr[j])//左右端点相等
                    dp[i][j] = dp[i+1][j-1];
                for(int k = i; k < j; k++) //左右端点 不相等,区间切开
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
            }
        }
        return dp[0][n-1];
    }
};

603ms C++


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!
Michael阿明

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页