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

版权声明:本博客的所有内容采用Creative Commons(知识共享)许可证,作者权利:署名(BY)& 非商业性使用(NC)。转载时请务必标明文章超链接、作者信息和本声明,禁止用于商业用途。 https://blog.csdn.net/thinkerleo1997/article/details/79120829

多段资源分配问题

题目内容

设有资源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个项目

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

项目\投资额度 1 2 3 4
1 0.23 0.35 0.36 0.49
2 0.22 0.36 0.39 0.54
3 0.38 0.45 0.90 0.45

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

对1号分配的资源数量 0 1 2 3 4
f1(x) 0 0.23 0.7 1.08 1.96

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

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

S\M 0 1 2 3 4 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号配的资源数量 0 1 2 3 4
f2(x) 0 0.23 0.72 1.17 2.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");
    }
}
阅读更多

没有更多推荐了,返回首页