1.整数拆分
递归公式
代码
// 题目描述:将正整数n无序拆分成最大数为k的拆分情况。拆分方案不重复
public static int split(int n,int k){
int [][] dp = new int[n+1][k+1];
dp[0][0] = 0;
int i, j;
for (i = 1; i <= n; i++){
for (j = 1; j <= k; j++){
// n = 1 ,k = 1时候 dp[i][j] = 1
if (i == 1 || j == 1){
dp[i][j] = 1;
}else if(i < j){
dp[i][j] = dp[i][i];
}else if (i == j){
dp[i][j] = dp[i][j-1] + 1;
}else if(i > j){
dp[i][j] = dp[i-j][j] + dp[i][j-1];
}
}
}
return dp[n][k];
}
2.最长公共子序列
递归公式
代码
// 求最长公共子序列的长度
public static int commonLen(String s1,String s2){
int len1 = s1.length();
int len2 = s2.length();
// 进行空与字符串比较 【特殊情况】
for (int i = 0; i <= len1; i++){
dp[i][0] = 0;
}
for (int i = 0; i <= len2;i++){
dp[0][i] = 0;
}
for (int i = 1; i <= len1; i++){
for (int j = 1; j <= len2;j++){
// 如果两者相等,则选择左上角+1
if (s1.charAt(i-1) == s2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
// 不相等,选择当前数上边和左边较大的数
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[len1][len2];
}
3.0/1背包
递推公式
代码
public static int knep(int f[][],int w[],int val[],int W,int n){
// 边界初始化操作:当W=0时候
for (int i = 0; i <= n;i++)
f[i][0] = 0;
// 边界初始化操作:当w[i] = 0的时候。
for (int r = 0; r <= W;r++)
f[0][r] = 0;
// 遍历操作
for (int i = 1; i <= n;i++){
for (int r=1; r <= W;r++){
// 装不下时候,不装。
if (r < w[i]){
f[i][r] = f[i-1][r];
}else{
// 装得下,比较是否要装入。
f[i][r] = Math.max(f[i-1][r],f[i-1][r-w[i]]+val[i]);
}
}
}
return f[n][W];
}
4.完全背包
递归公式:
代码
public static int solve(int w[],int f[][],int val[],int W,int n){
for (int i = 1; i <= n;i++){
for (int j = 1; j <= W;j++){
// 放不下
if (j - w[i-1] < 0){
f[i][j] = f[i-1][j];
}else{ // 放的下
// 放:几次
if (f[i-1][j] < f[i][j -w[i-1]] +val[i-1]){
// 注意这里是f[i][j-w[i]] 表示当前的物品能够放几次。
f[i][j] = f[i][j-w[i-1]] +val[i-1];
}else{
// 不放
f[i][j] = f[i-1][j];
}
}
}
}
return f[n][W];
}
5.最大连续子序列和
递推公式
代码
public static int[] lcs(int[]a){
int n = a.length;
int b[] = new int[n+1];
b[0] = a[0];
int j =1;
for (int i=1; i < n;i++){
b[j] = Math.max(b[j-1]+a[i],a[i]);
j++;
}
return b;
}
6.单调递增子序列
递推公式
代码
public static int lis(int [] a){
int len = a.length;
int b[] = new int[len];
b[0] = 1;
for (int i =1; i < len;i++){
int k = 0;
for (int j = 0; j < i; j++){
// 递增且获取之前存储过最大的连续递增长度
if (a[j] <= a[i] && k < b[j]){
k = b[j];
}
}
b[i] = k+1;
}
return b[len-1];
}