一. 区间DP简单介绍
区间DP,是经常会用到的、解决区间问题的一种方法,经常以动态规划(dfs/记忆化搜索)的形式展现,最核心的思想就是枚举区间(枚举端点),寻找切割点,处理因切割点而产生的结果,进行区间累加或者选取个别区间,从而解决整体的问题。
二. 区间DP模板
枚举区间
class Solution {
public int 区间dp(int[] v) {
int n = v.length;
int[][] dp = new int[n][n];
//枚举区间长度
for(int len = 满足题目要求的最小值; len <= n; len++){
//枚举左端点
for(int L = 0; L+len-1 < n; L++){
//枚举右端点
int R = L + len - 1;
//设置动态规划数组的初始值
dp[L][R] = maxvalue;
or
dp[L][R] = minvalue;
//枚举区间内的可能的切割点
for(int k = L+1; k < R; k++){
dp[L][R] = Math.min(dp[L][R], dp[L][k] ? dp[k][R] ? 因切割点而产生的特殊值);
}
}
}
//返回规定的区间范围
return dp[0][n-1];
or
return dp[1][n]
or
others
}
}
枚举端点
枚举端点的方法和枚举区间本质上都一样,有些题目反而用枚举端点的方法更容易思考
class Solution {
public int 区间dp(int[] v) {
int[][] dp = new int[v.length][v.length];
//枚举左端点,左端点经常从大到小枚举,为什么请看下文
for(int i = v.length-3; i >= 0; i--){
//枚举右端点
for(int j = i+2; j < v.length; j++){
//dp数组初始值
dp[i][j] = Integer.MAX_VALUE;
or
dp[i][j] = Integer.MIN_VALUE;
//枚举切割点
for(int k = i+1; k < j; k++){
dp[i][j] = Math.min(dp[i][j],dp[i][k]?dp[k][j]?因切割点而产生的特殊值);
}
}
}
return dp[0][v.length-1];
}
}
三. 区间DP经典案例
1.leetcode1312 让字符串成为回文串的最少插入次数
给你一个字符串 s ,每一次操作你都可以在字符串的任意位置插入任意字符。
请你返回让 s 成为回文串的 最少操作次数 。
「回文串」是正读和反读都相同的字符串。
输入:s = "mbadm"
输出