/**
* 0-1背包
*/
public class Knapsack {
public static void main(String[] args) {
int[] w = {2,2,6,5,4}; // 各个物品的重量
int[] v = {3,6,5,4,6}; // 各个物品的价值
int most_w = 10; // 背包最大容量
System.out.print("各个物品重量为:");
for (int i: w)
System.out.print(i + " ");
System.out.println();
System.out.print("各个物品的价值为:");
for (int i: v)
System.out.print(i + " ");
System.out.println();
System.out.println("背包最大容量为:"+most_w);
knapsack(w, v, most_w);
}
/**
* 0-1背包问题
* @param w:各个物品的重量
* @param v:各个物品的价值
* @param most_w:背包最大容量
*/
public static void knapsack(int[] w, int[] v, int most_w) {
// 获取物品的个数
int n = w.length;
// dp数组 从下标1 开始 (物品为0 或者 背包重量为0 的情况最大价值都为0, 默认值就是0 我们不需要处理)
int[][] c = new int[n+1][most_w+1];
for (int i=1; i<=n; i++) { // 从1-n 遍历物品个数
for (int j=1; j<=most_w; j++) { // 从0-most_w 递增背包容量
int weight = w[i-1];
int value = v[i-1];
if (weight <= j) // 如果背包可以放下该物品
c[i][j] = Math.max(c[i-1][j], c[i-1][j-weight]+value); // 尝试 放 或 不放 取最优值
else
c[i][j] = c[i-1][j]; // 放不下 最优值不变
}
}
System.out.println("最大价值为:"+ c[n][most_w]);
// 构造最优解
int[] x = new int[n];
int j = most_w; // 背包最大容量
for (int i=x.length; i>0; i--) { // 从后往前 随着物品减少 若当前最优解 大于 前一个物品最优解 则说明放入了该物品
if (c[i][j] > c[i-1][j]) {
x[i-1] = 1; // 1表示放入
j -= w[i-1];// j - 该物品的重量
}
}
System.out.print("最优解为:");
for (int i: x)
System.out.print(i + " ");
}
}
/**
* 最长公共子序列
*/
public class LCS {
public static void main(String[] args) {
String x = "ABCBDAB";
String y = "BDCABA";
int m = x.length();
int n = y.length();
// 动态数组
int[][] c = new int[m+1][n+1];
// 标记函数数组
int[][] b = new int[m+1][n+1];
// 上边界赋值为0
for (int i=0; i<=n; i++) {
c[0][i] = 0;
b[0][i] = 0;
}
// 左边界赋值为0
for (int i=0; i<=m; i++) {
c[i][0] = 0;
b[i][0] = 0;
}
System.out.println("字符串1:" + x);
System.out.println("字符串2:" + y);
LCSlength(m, n, x, y, c, b);
System.out.println("x,y 的最长公共子序列长度为:" + c[m][n]);
// 倒序输出 公共子序列
System.out.println("倒序输出 公共子序列:");
LCS(m, n, b, x);
}
/**
* 最长公共子序列
*/
public static void LCSlength(int m, int n, String x, String y, int[][] c, int[][] b) {
for (int i=1; i<=m; i++) {
for (int j=1; j<=n; j++) {
if (x.charAt(i-1) == y.charAt(j-1)) { // 若字符相同 c[i][j] = c[i-1][j-1] + 1;
c[i][j] = c[i-1][j-1] + 1;
b[i][j] = 1; // 1 代表 ↖
} else if (c[i][j-1] > c[i-1][j]) { // 字符不同取最大 c[i][j] = max(c[i][j-1], c[i-1][j])
c[i][j] = c[i][j-1];
b[i][j] = 2; // 2 代表 ←
} else {
c[i][j] = c[i-1][j];
b[i][j] = 3; // 3 代表 ↑
}
}
}
// 输出所填表
System.out.println("输出所填动归表:");
for (int i=0; i<=m; i++) {
for (int j=0; j<=n; j++) {
System.out.print(c[i][j] + " ");
}
System.out.println();
}
}
/**
* 输出 最长公共子序列 倒序输出
* @param i
* @param j
* @param b:标记函数数组
* @param x:x字符串
*/
public static void LCS(int i, int j, int[][] b, String x) {
if (i==0 || j==0) {
return;
}
// 1 表示 ↖
if (b[i][j] == 1) {
System.out.print(x.charAt(i-1) + " ");
// 输出该字符
LCS(i-1, j-1, b, x);
} else if (b[i][j] == 2) { // 2 表示 ←
LCS(i, j-1, b, x);
} else { // 3 表示 ↑
LCS(i-1, j, b, x);
}
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_45464560/article/details/125147359
内容来源于网络,如有侵权,请联系作者删除!