矩阵链相乘
运用迭代法实现。具体解法为:使用一个二维数组m来存储每个子问题的最优解,其中m[i][j]为计算矩阵ij所需的最小乘法次数,然后通过遍历矩阵链,更新m[i][j]。最后,返回m[0][n-1]作为整个问题的最优解,n为矩阵链的个数。
Java:
public static int matrixChainOrder(int[] p)
{
int n = p.length - 1;
int[][] m = new int[n][n];
for (int i = 0; i < n; i++)
{
m[i][i] = 0;
}
for (int len = 2; len <= n; len++)
{
for (int i = 0; i < n - len + 1; i++)
{
int j = i + len - 1;
m[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; k++)
{
int cost = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
if (cost < m[i][j])
{
m[i][j] = cost;
}
}
}
}
return m[0][n - 1];
}
python:
def matrix_chain_order(p):
n = len(p) - 1
m = [[0] * n for _ in range(n)]
for i in range(n):
m[i][i] = 0
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
m[i][j] = float('inf')
for k in range(i, j):
cost = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1]
if cost < m[i][j]:
m[i][j] = cost
return m[0][n - 1]
投资问题
m 元钱,n项投资, f_i (x): 将 x 元投入第 i 个项目的效益. 求使得效益最大的投资方案。
解法:
使用两层循环来填充数组。外层循环遍历项目的数量,内层循环遍历可用的投资金额。
Java:
public int max_profit(int m, int n, int[][] f)
{
int[][] dp = new int[n+1][m+1];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
dp[i][j] = dp[i-1][j]; // 不投资项目i
for (int x = 1; x <= j; x++)
{
dp[i][j] = Math.max(dp[i][j], dp[i-1][j-x] + f[i][x]); // 投资项目i
}
}
}
return dp[n][m];
}
python:
def max_profit(m, n, f):
dp = [[0] * (m+1) for _ in range(n+1)]
for i in range(1, n+1):
for j in range(1, m+1):
dp[i][j] = dp[i-1][j] # 不投资项目i
for x in range(1, j+1):
dp[i][j] = max(dp[i][j], dp[i-1][j-x] + f[i][x]) # 投资项目i
return dp[n][m]
背包问题
一个旅行者随身携带一个背包。可以放入背包的物品有n 种, 每种物品的重量和价值分别为 wi , vi . 如果背包的最大重量限制是 b, 每种物品可以放多个。怎 样选择放入背包的物品以使得背包的价值最大 ? 上述 wi , vi , b 都是正整数。
解法:
定义一个二维数组dp,其中dp[i][j]表示在前i种物品中,最大重量限制为j的情况下,背包中物品的最大价值。初始化dp数组的第一行和第一列都为0,表示没有物品或者背包容量为0时,背包中的价值都为0。通过遍历物品和背包重量的组合,计算dp数组的值。对于第i种物品,可以选择放入背包还是不放入背包。如果放入背包,那么背包的剩余重量为j-wi,此时背包中的价值为dp[i][j-wi] + vi。如果不放入背包,背包中的价值保持不变,即dp[i-1][j]。选取两种情况中的较大值作为dp[i][j]的值。最后,dp[n][b]即为所求,表示在前n种物品中,最大重量限制为b的情况下,背包中物品的最大价值。
python:
def knapsack(weights, values, n, b):
dp = [[0 for _ in range(b+1)] for _ in range(n+1)]
for i in range(1, n+1):
for j in range(1, b+1):
if weights[i-1] <= j:
dp[i][j] = max(dp[i-1][j], dp[i][j-weights[i-1]] + values[i-1])
else:
dp[i][j] = dp[i-1][j]
return dp[n][b]
Java:
public int knapsack(int[] weights, int[] values, int n, int b)
{
int[][] dp = new int[n+1][b+1];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= b; j++)
{
if (weights[i-1] <= j)
{
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-weights[i-1]] + values[i-1]);
} else
{
dp[i][j] = dp[i-1][j];
}
}
}
return dp[n][b];
}
字符串最长公共子序列
解法:
遍历两个字符串,对获取到的字符串进行迭代。
python:
def LCS(str1, str2):
m = len(str1)
n = len(str2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if str1[i - 1] == str2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
lcs = ''
i = m
j = n
while i > 0 and j > 0:
if str1[i - 1] == str2[j - 1]:
lcs = str1[i - 1] + lcs
i -= 1
j -= 1
elif dp[i - 1][j] > dp[i][j - 1]:
i -= 1
else:
j -= 1
return lcs
Java:
public static String LCS(String str1, String str2)
{
int m = str1.length();
int n = str2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (str1.charAt(i - 1) == str2.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]);
}
}
}
StringBuilder lcs = new StringBuilder();
int i = m;
int j = n;
while (i > 0 && j > 0)
{
if (str1.charAt(i - 1) == str2.charAt(j - 1))
{
lcs.insert(0, str1.charAt(i - 1));
i--;
j--;
} else if (dp[i - 1][j] > dp[i][j - 1])
{
i--;
} else {
j--;
}
}
return lcs.toString();
}
本文仅为学习记录,如有错误欢迎指出。