1. 题目
描述 有n个瓶子排成一列,用arr表示。 你每次可以选择能够形成回文连续子串的瓶子拿走,剩下的瓶子拼接在一起。 返回你能拿走所有的瓶子的最小次数。
代码语言:javascript复制n<=500
arr[i]<=1000
示例
代码语言:javascript复制例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
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