算法实现之动态规划算法实现

矩阵链相乘

运用迭代法实现。具体解法为:使用一个二维数组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();
        }

本文仅为学习记录,如有错误欢迎指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值