当前位置:   article > 正文

数据结构与算法之动态规划算法_数据结构c语言版动态规划

数据结构c语言版动态规划

动态规划算法是解决最优化问题的一种常用算法,它适用于具有重复子问题和最优子结构的问题。它将问题分解成子问题,并使用已解决的子问题的解来计算原问题的解。动态规划算法可以优化递归算法的时间复杂度,因为它避免了重复计算。下面是动态规划算法的基本步骤:

  1. 定义状态:确定问题的最优子结构,将问题划分为更小的子问题。
  2. 定义状态转移方程:根据问题的最优子结构,使用递推公式或递归式来计算子问题的解,并使用子问题的解构建原问题的解。
  3. 计算初始状态:计算初始子问题的解。
  4. 计算最终状态:计算原问题的解。
  5. 状态压缩:对状态进行压缩,以减小空间复杂度。

动态规划算法可以应用于各种问题,如背包问题、最长公共子序列问题、最短路径问题等。

在这里插入图片描述

一、C 实现动态规划算法及代码详解

动态规划是一种常用的算法思想,常用于求解最优化问题。它和贪心算法类似,但是需要满足一定的条件才能使用。

动态规划的主要特点是使用了子问题重叠的性质,即一个较大的问题可以被拆解成若干个相似的子问题来进行求解,并且这些子问题的结果可以被重复利用。

动态规划算法的一般步骤如下:

  1. 找到子问题的重叠性质,确定递推式。

  2. 确定递推式的起点。

  3. 编写代码实现递推。

下面是一个实现动态规划算法的示例代码,用于求解斐波那契数列的第n项。

#include <stdio.h>

int fib(int n)
{
    int dp[n + 1];
    dp[0] = 0;
    dp[1] = 1;

    for (int i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }

    return dp[n];
}

int main()
{
    int n;
    printf("Enter n: ");
    scanf("%d", &n);

    printf("fib(%d) = %d\n", n, fib(n));

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

在这个示例中,我们使用了一个数组dp来存储斐波那契数列的中间结果,利用递推式dp[i] = dp[i - 1] + dp[i - 2]进行计算。递推的起点是dp[0] = 0dp[1] = 1

通过以上步骤,我们就能够使用动态规划算法来求解斐波那契数列的第n项了。

总结一下,动态规划是一种基于子问题重叠性质的算法,它可以用于求解一些最优化问题,并且能够有效地降低问题的时间复杂度。在实际应用中,我们需要根据具体问题找出适合的子问题重叠性质,并利用递推式计算出中间结果,最终得到最优解。

在这里插入图片描述

二、C++ 实现动态规划算法及代码详解

动态规划是一种经典的算法思想,它是针对一类重复出现的子问题,通过存储过程的计算结果,将这些子问题的解存储起来,以便在需要相同结果的时候进行复用,从而减少重复计算,提高算法效率。下面我们将通过一个具体的例子来介绍如何使用 C++ 实现动态规划算法。

问题描述:有一排 n 个房子,每个房子可以被涂上红色、绿色和蓝色三种颜色之一。你必须将所有房子涂上颜色,相邻的房子不能涂上相同的颜色,求所有可能的方案数。

解题思路:我们可以使用动态规划来解决这个问题。假设我们已经求得了前 i-1 个房子的所有可能方案数,现在考虑如何求得前 i 个房子的方案数。假设前 i-1 个房子的最后一个房子涂的颜色为红色,则第 i 个房子可以涂上绿色或蓝色,此时前 i 个房子的方案数为前 i-1 个房子最后一个房子为绿色或蓝色的方案数之和。同理,如果前 i-1 个房子最后一个房子涂的颜色为绿色或蓝色,则第 i 个房子可以涂上红色或另一个颜色,此时前 i 个房子的方案数仍为前 i-1 个房子最后一个房子为绿色或蓝色的方案数之和。

接下来我们来详细编写这段动态规划算法的代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 7;
const int mod = 1e9 + 7;
int f[N][3];  // f[i][j]表示前i个房子,最后一个房子涂上颜色j的方案数

int main()
{
    int n;
    cin>>n;
    memset(f,0,sizeof(f));
    f[1][0] = f[1][1] = f[1][2] = 1;  // 初始化

    for(int i = 2;i <= n;i++)
    {
        f[i][0] = (f[i-1][1] + f[i-1][2]) % mod;
        f[i][1] = (f[i-1][0] + f[i-1][2]) % mod;
        f[i][2] = (f[i-1][0] + f[i-1][1]) % mod;
    }

    cout<<(f[n][0] + f[n][1] + f[n][2]) % mod<<endl;  // 输出总方案数
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这段代码中,我们使用一个二维数组 f[N][3] 来存储每个子问题的解,f[i][j] 表示前 i 个房子中最后一个房子涂上颜色 j 的方案数。我们先将 f 数组初始化为 0,然后将前一个房子的方案数全部设置为 1,即 f[1][0] = f[1][1] = f[1][2] = 1。接着,通过一个 for 循环,从 i=2 开始枚举每个房子,按照上述思路计算 f[i][j] 的值,并存储到 f 数组中。最后,输出 f[n][0] + f[n][1] + f[n][2] 的值即为总方案数。

在这里插入图片描述

三、Java 实现动态规划算法及代码详解

动态规划是一种重要的算法思想,用于解决优化问题。它的核心思想是将一个大问题分解成若干个小问题,通过解决这些小问题来得到整个问题的最优解。

Java 语言可以很方便地实现动态规划算法。下面我们以背包问题为例,介绍一下如何使用 Java 实现动态规划算法。

背包问题是一种经典的优化问题,它的描述如下:

有一个容量为 W 的背包,以及 n 个物品,每个物品有一个重量和一个价值。你需要选择一些物品放入背包中,使得它们的总重量不超过 W,同时总价值最大。

我们可以使用动态规划算法来解决这个问题。具体来说,我们可以定义一个二维数组 dp,其中 dp[i][j] 表示在前 i 个物品中选择一些放入容量为 j 的背包中可以得到的最大价值。根据这个定义,我们可以得到动态规划的转移方程:

dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])

其中 w[i] 和 v[i] 分别表示第 i 个物品的重量和价值。这个转移方程的意义是,我们可以选择不放第 i 个物品,那么最大价值就是前 i-1 个物品在容量为 j 的背包中可以得到的最大价值;或者选择放第 i 个物品,那么最大价值就是前 i-1 个物品在容量为 j-w[i] 的背包中可以得到的最大价值加上第 i 个物品的价值。

根据这个动态规划的转移方程,我们可以使用 Java 来实现一个背包问题的解决方案。代码如下:

public class Knapsack {
    public static void main(String[] args) {
        int W = 10;
        int[] w = {2, 3, 4, 5};
        int[] v = {3, 4, 5, 6};
        int n = w.length;

        int[][] dp = new int[n + 1][W + 1];

        // 初始化边界条件
        for (int j = 0; j <= W; j++) {
            dp[0][j] = 0;
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= W; j++) {
                if (j < w[i-1]) {
                    dp[i][j] = dp[i-1][j];
                } else {
                    dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1]);
                }
            }
        }

        System.out.println(dp[n][W]);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这个代码中,我们首先定义了容量为 W 的背包,以及物品的重量和价值数组 w 和 v,还有物品的个数 n。然后我们定义了一个二维数组 dp,用来保存各种状态下的最大价值。

在初始化边界条件之后,我们可以使用两层循环来逐步计算 dp 数组。在循环中,我们分别遍历了所有物品和所有背包容量,根据动态规划的转移方程来计算 dp[i][j] 的值。

最后,我们输出 dp[n][W] 的值,即为我们要求的最大价值。

总之,Java 语言非常适合实现动态规划算法。通过定义好状态转移方程,并使用适当的循环来计算状态,我们可以很容易地解决各种优化问题。

在这里插入图片描述

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号