动态规划法-资源分配问题

动态规划法 - 资源分配问题

问题描述

把4个份额的资源分配给3个工程,给定利润表如下表所示,写出资源的最优分配方案的求解过程。
在这里插入图片描述
4份资源分配给3个工程的利润表

步骤一:求各个阶段不同分配份额时的最大利润及分配份额

目标

我们的目标是找到在给定资源限制下,如何分配资源给不同的工程以获得最大利润。

步骤

  1. 定义子问题:我们定义 fᵢ(x) 为将 x 份资源分配给前 i 个工程时的最大利润,dᵢ(x) 为在 fᵢ(x) 最大时,分配给第 i 个工程的资源份额。
  2. 初始化:对于只有一个工程的情况,我们可以直接计算出 f₁(x)d₁(x)
  3. 迭代计算:对于更多的工程,我们使用已知的 f₋₁(x)d₋₁(x) 来计算 fᵢ(x)dᵢ(x)

1. 只分配给第1个工程

资源分配表:

x01234
f₁(x)713161719
d₁(x)01234

解释:

  • 我们首先考虑只有一个工程的情况,直接计算每个资源份额下的利润。
  • d₁(x) 表示在给定资源份额下,第1个工程的资源分配。

2. 分配给前2个工程

资源分配表:

x01234
f₂(x)1319252830
d₂(x)00/1112

计算过程:

  1. 当 x = 0 时:

    • 只有第1个工程可以使用资源,利润为 f₂(0) = f₁(0) + G₂(0) = 7 + 6 = 13
    • 资源全部分配给第1个工程,d₂(0) = 0
  2. 当 x = 1 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₂(0) + f₁(1) = 6 + 13 = 19
      • G₂(1) + f₁(0) = 12 + 7 = 19
    • 利润相同,可以选择任意一种分配方式,d₂(1) 可以是 0 或 1。
  3. 当 x = 2 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₂(0) + f₁(2) = 6 + 16 = 22
      • G₂(1) + f₁(1) = 12 + 13 = 25
      • G₂(2) + f₁(0) = 14 + 7 = 21
    • 选择利润最大的分配方式,d₂(2) = 1
  4. 当 x = 3 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₂(0) + f₁(3) = 6 + 17 = 23
      • G₂(1) + f₁(2) = 12 + 16 = 28
      • G₂(2) + f₁(1) = 14 + 13 = 27
      • G₂(3) + f₁(0) = 16 + 7 = 23
    • 选择利润最大的分配方式,d₂(3) = 1
  5. 当 x = 4 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₂(0) + f₁(4) = 6 + 19 = 25
      • G₂(1) + f₁(3) = 12 + 17 = 29
      • G₂(2) + f₁(2) = 14 + 16 = 30
      • G₂(3) + f₁(1) = 16 + 13 = 29
      • G₂(4) + f₁(0) = 18 + 7 = 25
    • 选择利润最大的分配方式,d₂(4) = 2

解释为什么这么做:

  • 我们通过比较不同分配方式下的利润,选择能够带来最大利润的分配方案。
  • 这种方法确保了在有限的资源下,我们能够获得最大的经济回报。
  • 动态规划的优势在于它避免了重复计算相同的子问题,提高了计算效率。

通过以上步骤,我们可以得到在不同资源分配下的最大利润以及各个工程的资源分配份额。

3. 分配给前3个工程

步骤

  1. 定义子问题:我们定义 f₃(x) 为将 x 份资源分配给前3个工程时的最大利润,d₃(x) 为在 f₃(x) 最大时,分配给第3个工程的资源份额。

计算过程

  1. 当 x = 0 时:

    • 只有第1和第2个工程可以使用资源,利润为 f₃(0) = f₁(0) + G₂(0) + G₃(0) = 7 + 6 + 5 = 18
    • 资源全部分配给第1和第2个工程,d₃(0) = 0
  2. 当 x = 1 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₃(0) + f₂(1) = 5 + 19 = 24
      • G₃(1) + f₂(0) = 18 + 13 = 31
    • 选择利润最大的分配方式,d₃(1) = 1
  3. 当 x = 2 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₃(0) + f₂(2) = 5 + 25 = 30
      • G₃(1) + f₂(1) = 18 + 19 = 37
      • G₃(2) + f₂(0) = 19 + 13 = 32
    • 选择利润最大的分配方式,d₃(2) = 1
  4. 当 x = 3 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₃(0) + f₂(3) = 5 + 28 = 33
      • G₃(1) + f₂(2) = 18 + 25 = 43
      • G₃(2) + f₂(1) = 19 + 19 = 38
      • G₃(3) + f₂(0) = 20 + 13 = 33
    • 选择利润最大的分配方式,d₃(3) = 1
  5. 当 x = 4 时:

    • 比较不同分配方式的利润,选择最大的利润:
      • G₃(0) + f₂(4) = 5 + 30 = 35
      • G₃(1) + f₂(3) = 18 + 28 = 46
      • G₃(2) + f₂(2) = 19 + 25 = 44
      • G₃(3) + f₂(1) = 20 + 19 = 39
      • G₃(4) + f₂(0) = 22 + 13 = 35
    • 选择利润最大的分配方式,d₃(4) = 1

资源分配表:

xf₃(x)d₃(x)
0180
1311
2371
3431
4461

解释为什么这么做

  • 我们通过比较不同分配方式下的利润,选择能够带来最大利润的分配方案。
  • 这种方法确保了在有限的资源下,我们能够获得最大的经济回报。
  • 动态规划的优势在于它避免了重复计算相同的子问题,提高了计算效率。

步骤二:求各个阶段的最大利润 gᵢ 和分配份额 qᵢ

  • 最大利润

    • g₁ = 19
    • g₂ = 30
    • g₃ = 46
  • 资源分配份额

    • q₁ = 4
    • q₂ = 4
    • q₃ = 4

步骤三:计算全局的最大利润 optg、最大的工程数目 k、总的最优分配份额 optx(k)

  • 全局最大利润optg = 46
  • 最大的工程数目k = 3
  • 总的最优分配份额optx₃ = 4

步骤四: 计算各个工程的最优分配份额 optq(x)

  1. 第3个工程

    • optq₃ = d₃(optx₃) = d₃(4) = 1
    • optx₂ = optx₃ - optq₃ = 4 - 1 = 3
  2. 第2个工程

    • optq₂ = d₂(optx₂) = d₂(3) = 1
    • optx₁ = optx₂ - optq₂ = 3 - 1 = 2
  3. 第1个工程

    • optq₁ = d₁(optx₁) = d₁(2) = 2

最终决策结果

  • 分别分配给第1、2、3工程 2、1、1 份资源,可得最大利润 46。

代码

/* 资源分配问题 */
#include <stdio.h>
#define N 7  // 定义常量 N,代表项目的数量
#define M 3  // 定义常量 M,代表资源的种类数量
float profit[M+1][N+1];  // 存储不同资源分配方案下的利润,M+1 和 N+1 是因为数组是从 1 开始计数的

// 测试数据,代表不同资源分配下的利润
float test[24] = {0, 0.11, 0.13, 0.15, 0.21, 0.24, 0.3, 0.35,
                  0, 0.12, 0.16, 0.21, 0.23, 0.25, 0.24, 0.34,
                  0, 0.08, 0.12, 0.2,  0.24, 0.25, 0.3, 0.35};

int main() {
    float temp[N+1];  // 用来存储当前正在计算的最大利润
    float f[N+1];  // 用来存储当前的最大利润
    int a[M+1][N+1];  // 资源分配表,包括分配为0的情况
    int gain[M];  // 用来存储每个项目最终分配的资源数量
    int number = 0;  // 用来记录测试数据的索引

    // 给初始的利润表 profit 赋值
    for (int i = 0; i <= M; i++) {
        for (int j = 0; j <= N; j++) {
            profit[i][j] = test[number++];  // 从测试数据中获取利润值
            if (i < 1) {
                // 如果是第一个项目,初始化资源分配表
                a[1][j] = j;  // 分配所有资源给第一个项目
                f[j] = profit[0][j];  // 初始化当前的最大利润
                temp[j] = profit[0][j];  // 存储只有一个项目时的最大利润
            }
        }
    }

    int layer = 0;  // 用来记录当前处理的项目层级
    for (int k = 2; k <= M; k++) {  // 依次加入新项目
        layer++;
        for (int i = 0; i <= N; i++) {  // 不同资源数量的分配方案
            for (int j = 0; j <= i; j++) {  // 分配给新项目的资源数
                if (profit[layer][j] + temp[i - j] > f[i]) {  // 如果新分配方案的利润更高
                    f[i] = profit[layer][j] + temp[i - j];  // 更新当前的最大利润
                    a[k][i] = j;  // 记录新项目的资源分配
                    printf("sum3=%3.2f\n", f[i]);  // 打印当前的最大利润
                }
            }
        }
        for (int j = 0; j <= N; j++) {  // 更新已计算的项目资源分配利益总表
            temp[j] = f[j];
        }
        printf("第一次结束:\n");
    }

    int rest = N;  // 剩余的资源数量
    for (int i = M; i >= 1; i--) {  // 记录每个项目的资源分配情况
        gain[i] = a[i][rest];  // 记录第 i 个项目分配的资源数量
        rest = rest - gain[i];  // 更新剩余的资源数量
    }

    for (int i = 1; i <= M; i++) {  // 打印每个项目的资源分配情况
        printf("第%d个项目投资%d万元\n", i, gain[i]);
    }
    printf("sum=%3.2f:\n", f[N]);  // 打印总的最大利润
}

在这里插入图片描述

实验课程:算法分析与设计 实验名称:用动态规划求解资源分配问题 (验证型实验) 实验目标: (1)掌握用动态规划求解实际问题的基本思路。 (2)进一步理解动态规划的实质,巩固设计动态规划算法的基本步骤。 实验任务: (1)设计动态规划算法求解资源分配问题,给出算法的非形式描述。 (2) 在Windows环境下用C 语言实现该算法。计算10个实例,每个实例中n=30, m=10, Ci j为随机产生于范围(0,103)内的整数。记录各实例的数据及执行结果(即最优分配方案、最优分配方案的值)、运行时间。 (3)从理论上分析算法的时间和空间复杂度,并由此解释相应的实验结果。 实验设备及环境: PC;C/C++等编程语言。 实验主要步骤: (1) 根据实验目标,明确实验的具体任务; (2) 分析资源分配问题,获得计算其最优值的递推计算公式; (3) 设计求解问题的动态规划算法,并编写程序实现算法; (4) 设计实验数据并运行程序、记录运行的结果; (5) 分析算法的时间和空间复杂度,并由此解释释相应的实验结果; 问题分析: 问题描述: 某厂根据计划安排,拟将n台相同的设备分配给m个车间,各车间获得这种设备后,可以为国家提供盈利Ci j(i台设备提供给j号车间将得到的利润,1≤i≤n,1≤j≤m) 。问如何分配,才使国家得到最大的盈利? 算法基本思想: 本问题是一简单资源分配问题,由于具有明显的最优子结构,故可以使用动态规划求解,用状态量f[i][j]表示用i台设备分配给前j个车间的最大获利,那么显然有f[i][j] = max{ f[k][j–1] + c[i-k][j] },0<=k<=i。再用p[i][j]表示获得最优解时第j号车间使用的设备数为i-p[i][j],于是从结果倒推往回求即可得到分配方案。程序实现时使用顺推,先枚举车间数,再枚举设备数,再枚举状态转移时用到的设备数,简单3重for循环语句即可完成。时间复杂度为O(n^2*m),空间复杂度为O(n*m),倘若此题只需求最大获利而不必求方案,则状态量可以减少一维,空间复杂度优化为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值