多段资源分配问题(动态规划)

多段资源分配问题

题目内容

设有资源n(n为整数),分配给m个项目, gi(x) 为第i个项目分得资源 x 所得到的利润,求总利润最大的资源分配方案, 也就是解下列问题:
max z=g1(x1)+g2(x2)+...+gm(xm)
x1+x2+...+xm=n , 0x1nxi, i=1,2,3...,m

方法一:暴力法 orz

思路

简单来说就是把每一种情况试一遍,时间复杂度嘛。。。不存在的( O(2N) )
采用多重循环或者递归,时间复杂度太高,这里不讨论。

方法二:动态规划

思路

假设 fi(x) 为将资源x分给前i个项目所获得的最大利润,得出状态转移方程:

{f1(x)=gi(x)    0xnfi(x)=max(gi(x)+fi1(nx))    0xn

假设:

const int RESOURCE = 4; //有4个资源
const int CASE_NUM = 3; //3个项目

每个项目对应额度的利率:

项目\投资额度1234
10.230.350.360.49
20.220.360.390.54
30.380.450.900.45

首先对1号竞争者进行资源分配

对1号分配的资源数量01234
f1(x) 00.230.71.081.96

那么2号资源和2号资源一起分配的情况:

对1,2一共分配的资源数为S
2号项目分配资源数为M

S\M01234 fi(x)
1..# f1(1) f1(11)+10.22 0.23
2.. f1(2) f1(21)+10.22 # f1(22)+20.36 0.72
3.. f1(3) f1(31)+10.22 f1(32)+20.36 # f1(33)+30.39 1.17
4.. f1(4) f1(41)+10.22 f1(42)+20.36 f1(43)+30.39 # f1(44)+40.54 2.16

将1和2的状态合并:

对1号分和2号配的资源数量01234
f2(x) 00.230.721.172.16

同理, 计算 f3(x) 时, 使用上面方法计算

代码实现:

#include <iostream>

using namespace std;

const int RESOURCE = 4; //资源数量
const int CASE_NUM = 3; //项目数量
//各个项目对应投资量的收益率
const double RATE[CASE_NUM][RESOURCE+1] = {{0, 0.23, 0.35, 0.36, 0.49},
                                         {0, 0.22, 0.36, 0.39, 0.54},
                                         {0, 0.38, 0.45, 0.9, 0.45}};
//保存前i个项目的对于每个资源的最大收益的数组(可以用一维数组代替,这里为debug方便) 
double array[100][100] = {0};

int main(){
    //初始化第一个项目的各个投资数的最佳收益
    for(int i = 0; i <= RESOURCE; i++){
        array [0][i] =  i*RATE[0][i];
    }

    int all = 0;    //all为目前已经投资的资源数
    for(int i = 1; i < CASE_NUM; i++){ //求每个项目的投资数
        int y = 0; //第i - 1 项目要投资的资源
        for(int j = 0; j <= RESOURCE; j++){ ////给前i个项目总共分配的资源,项目投资数 0~RESOURCE
            double maxx = 0;    //当前投资数下最大盈利
            for(int k = 0; k <= j; k++){    //给第i个投资k个资源, k < = RESOURCE
                double temp = array[i - 1][j - k] + k * RATE[i][k];
                if(temp >= maxx){
                    maxx = temp;
                    y = j - k;
                }
            }
            array[i][j] = maxx;
        }
        all += y;
        printf("%d 号CASE投资 %d个\n", i-1, y);
    }
    printf("%d 号CASE投资 %d个\n", CASE_NUM - 1, RESOURCE - all);

    //打印每个项目对于每个数量资源的最大收益的数组(可以省略不要,这里为debug方便) 
    for(int i = 0; i < CASE_NUM; i++){
        for(int j = 0; j <= RESOURCE; j++){
            printf("%lf ", array[i][j]);
        }
        printf("\n");
    }
}
    原文作者:动态规划
    原文地址: https://blog.csdn.net/thinkerleo1997/article/details/79120829
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞