1. 斐波那契数列(Fibonacci Sequence)
描述:
斐波那契数列是一个数列,其中每个数字是前两个数字的和,通常形式为0, 1, 1, 2, 3, 5, 8, 13, …。动态规划方法用于计算第n个斐波那契数。
Java案例:
public class Fibonacci {
public static int fibonacci(int n) {
if (n <= 1) {
return n;
}
int prev = 0, curr = 1;
for (int i = 2; i <= n; i++) {
int next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
public static void main(String[] args) {
int n = 10;
System.out.println("Fibonacci number at position " + n + " is: " + fibonacci(n));
}
}
2. 背包问题(Knapsack Problem)
描述:
0/1背包问题是动态规划中的经典问题,给定一组物品,每个物品有其重量和价值,在限定的总重量内,选择物品以使得总价值最大。
Java案例:
public class Knapsack {
public static int knapsack(int[] weights, int[] values, int capacity) {
int n = weights.length;
int[][] dp = new int[n + 1][capacity + 1];
for (int i = 1; i <= n; i++) {
for (int w = 1; w <= capacity; w++) {
if (weights[i - 1] <= w) {
dp[i][w] = Math.max(values[i - 1] + dp[i - 1][w - weights[i - 1]], dp[i - 1][w]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][capacity];
}
public static void main(String[] args) {
int[] values = {60, 100, 120};
int[] weights = {10, 20, 30};
int capacity = 50;
System.out.println("Maximum value in knapsack = " + knapsack(weights, values, capacity));
}
}
3. 编辑距离(Edit Distance)
描述:
编辑距离(Levenshtein距离)是指将一个字符串转换为另一个字符串所需的最少操作数,包括插入、删除和替换。
Java案例:
public class EditDistance {
public static int editDistance(String s1, String s2) {
int m = s1.length(), n = s2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0) dp[i][j] = j;
else if (j == 0) dp[i][j] = i;
else if (s1.charAt(i - 1) == s2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];
else dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
}
}
return dp[m][n];
}
public static void main(String[] args) {
String s1 = "sunday";
String s2 = "saturday";
System.out.println("Edit Distance between " + s1 + " and " + s2 + " is " + editDistance(s1, s2));
}
}
4. 最长公共子序列(Longest Common Subsequence)
描述:
最长公共子序列问题是找出两个序列的最长子序列,该子序列必须是两个序列的子序列。
Java案例:
public class LongestCommonSubsequence {
public static int lcs(String X, String Y) {
int m = X.length();
int n = Y.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0) dp[i][j] = 0;
else if (X.charAt(i - 1) == Y.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[m][n];
}
public static void main(String[] args) {
String X = "ABCBDAB";
String Y = "BDCABC";
System.out.println("Length of LCS is " + lcs(X, Y));
}
}
5. 最长递增子序列(Longest Increasing Subsequence)
描述:
最长递增子序列问题是找出一个数组中的最长递增子序列。
Java案例:
public class LongestIncreasingSubsequence {
public static int lis(int[] arr) {
int n = arr.length;
int[] dp = new int[n];
int maxLength = 0;
for (int i = 0; i < n; i++) {
dp[i] = 1; // A single element is a subsequence of itself
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i] && 1 + dp[j] > dp[i]) {
dp[i] = 1 + dp[j];
}
}
if (dp[i] > maxLength) {
maxLength = dp[i];
}
}
return maxLength;
}
public static void main(String[] args) {
int[] arr = {10, 22, 9, 33, 21, 50, 41, 60};
System.out.println("Length of LIS is " + lis(arr));
}
}
这些案例展示了动态规划在解决不同问题中的应用,包括计算斐波那契数列、解决背包问题、计算编辑距离、寻找最长公共子序列和最长递增子序列。动态规划是一种强大的算法技术,通过将问题分解为更小的子问题来解决问题。